From 9afe0f2cd43681ed60a25547d5ceafed3174bf71 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 23 Oct 2019 02:49:53 +0700 Subject: [PATCH 1/7] Sync changes with miner. --- src/base/api/Api.cpp | 10 +- src/base/api/Api.h | 5 +- src/base/base.cmake | 13 +- src/base/io/json/Json.cpp | 21 ++ src/base/io/log/Log.cpp | 17 +- src/base/io/log/backends/ConsoleLog.cpp | 12 +- src/base/io/log/backends/ConsoleLog.h | 6 +- src/base/kernel/Base.cpp | 82 ++--- src/base/kernel/Base.h | 4 + src/base/kernel/Entry.cpp | 23 +- src/base/kernel/Entry.h | 3 +- src/base/kernel/Platform.cpp | 12 +- src/base/kernel/Platform.h | 10 +- src/base/kernel/Platform_hwloc.cpp | 49 +++ src/base/kernel/Platform_mac.cpp | 16 +- src/base/kernel/Platform_unix.cpp | 16 +- src/base/kernel/Platform_win.cpp | 20 +- src/base/kernel/Process.cpp | 7 +- src/base/kernel/Process.h | 1 - src/base/kernel/config/BaseConfig.h | 1 - src/base/kernel/config/BaseTransform.cpp | 29 +- src/base/kernel/config/BaseTransform.h | 4 +- src/base/kernel/interfaces/IClient.h | 55 ++-- src/base/kernel/interfaces/IClientListener.h | 2 +- src/base/kernel/interfaces/IConfig.h | 5 + src/base/net/http/HttpClient.cpp | 14 +- src/base/net/http/HttpClient.h | 7 +- src/base/net/http/HttpContext.cpp | 8 +- src/base/net/http/HttpContext.h | 15 +- src/base/net/http/HttpsClient.cpp | 2 +- src/base/net/http/HttpsClient.h | 10 +- src/base/net/stratum/BaseClient.cpp | 35 +- src/base/net/stratum/BaseClient.h | 25 +- src/base/net/stratum/Client.cpp | 101 ++++-- src/base/net/stratum/Client.h | 9 +- src/base/net/stratum/DaemonClient.h | 21 +- src/base/net/stratum/Job.cpp | 48 ++- src/base/net/stratum/Job.h | 64 ++-- src/base/net/stratum/Pool.cpp | 234 +++++--------- src/base/net/stratum/Pool.h | 53 +-- src/base/net/stratum/Pools.cpp | 10 +- src/base/net/stratum/SelfSelectClient.cpp | 306 ++++++++++++++++++ src/base/net/stratum/SelfSelectClient.h | 123 +++++++ src/base/net/stratum/SubmitResult.h | 22 +- src/base/net/stratum/Url.cpp | 163 ++++++++++ src/base/net/stratum/Url.h | 77 +++++ .../stratum/strategies/FailoverStrategy.cpp | 23 +- .../net/stratum/strategies/FailoverStrategy.h | 3 + .../stratum/strategies/SinglePoolStrategy.cpp | 23 +- .../stratum/strategies/SinglePoolStrategy.h | 3 + src/base/tools/Buffer.cpp | 21 +- src/base/tools/Buffer.h | 14 +- src/base/tools/String.cpp | 21 +- src/base/tools/String.h | 13 +- src/core/config/usage.h | 17 +- 55 files changed, 1372 insertions(+), 536 deletions(-) create mode 100644 src/base/kernel/Platform_hwloc.cpp create mode 100644 src/base/net/stratum/SelfSelectClient.cpp create mode 100644 src/base/net/stratum/SelfSelectClient.h create mode 100644 src/base/net/stratum/Url.cpp create mode 100644 src/base/net/stratum/Url.h diff --git a/src/base/api/Api.cpp b/src/base/api/Api.cpp index f358ac4b4..22f00b774 100644 --- a/src/base/api/Api.cpp +++ b/src/base/api/Api.cpp @@ -117,9 +117,10 @@ void xmrig::Api::exec(IApiRequest &request) auto &allocator = request.doc().GetAllocator(); request.accept(); - request.reply().AddMember("id", StringRef(m_id), allocator); - request.reply().AddMember("worker_id", StringRef(m_workerId), allocator); - request.reply().AddMember("uptime", (Chrono::currentMSecsSinceEpoch() - m_timestamp) / 1000, allocator); + request.reply().AddMember("id", StringRef(m_id), allocator); + request.reply().AddMember("worker_id", StringRef(m_workerId), allocator); + request.reply().AddMember("uptime", (Chrono::currentMSecsSinceEpoch() - m_timestamp) / 1000, allocator); + request.reply().AddMember("restricted", request.isRestricted(), allocator); Value features(kArrayType); # ifdef XMRIG_FEATURE_API @@ -139,6 +140,9 @@ void xmrig::Api::exec(IApiRequest &request) # endif # ifdef XMRIG_FEATURE_TLS features.PushBack("tls", allocator); +# endif +# ifdef XMRIG_FEATURE_OPENCL + features.PushBack("opencl", allocator); # endif request.reply().AddMember("features", features, allocator); } diff --git a/src/base/api/Api.h b/src/base/api/Api.h index 334609c95..0c1a728db 100644 --- a/src/base/api/Api.h +++ b/src/base/api/Api.h @@ -27,10 +27,11 @@ #include -#include +#include #include "base/kernel/interfaces/IBaseListener.h" +#include "base/tools/Object.h" namespace xmrig { @@ -47,6 +48,8 @@ class String; class Api : public IBaseListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Api) + Api(Base *base); ~Api() override; diff --git a/src/base/base.cmake b/src/base/base.cmake index bc022c70c..615d9ac5e 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -41,6 +41,7 @@ set(HEADERS_BASE src/base/net/stratum/strategies/FailoverStrategy.h src/base/net/stratum/strategies/SinglePoolStrategy.h src/base/net/stratum/SubmitResult.h + src/base/net/stratum/Url.h src/base/net/tools/RecvBuf.h src/base/net/tools/Storage.h src/base/tools/Arguments.h @@ -78,6 +79,7 @@ set(SOURCES_BASE src/base/net/stratum/Pools.cpp src/base/net/stratum/strategies/FailoverStrategy.cpp src/base/net/stratum/strategies/SinglePoolStrategy.cpp + src/base/net/stratum/Url.cpp src/base/tools/Arguments.cpp src/base/tools/Buffer.cpp src/base/tools/String.cpp @@ -98,7 +100,14 @@ elseif (APPLE) else() set(SOURCES_OS src/base/io/json/Json_unix.cpp - src/base/kernel//Platform_unix.cpp + src/base/kernel/Platform_unix.cpp + ) +endif() + + +if (WITH_HWLOC) + list(APPEND SOURCES_OS + src/base/kernel/Platform_hwloc.cpp ) endif() @@ -130,6 +139,7 @@ if (WITH_HTTP) src/base/net/http/HttpResponse.h src/base/net/http/HttpServer.h src/base/net/stratum/DaemonClient.h + src/base/net/stratum/SelfSelectClient.h src/base/net/tools/TcpServer.h ) @@ -145,6 +155,7 @@ if (WITH_HTTP) src/base/net/http/HttpResponse.cpp src/base/net/http/HttpServer.cpp src/base/net/stratum/DaemonClient.cpp + src/base/net/stratum/SelfSelectClient.cpp src/base/net/tools/TcpServer.cpp ) diff --git a/src/base/io/json/Json.cpp b/src/base/io/json/Json.cpp index 07986c4af..03d4c65ab 100644 --- a/src/base/io/json/Json.cpp +++ b/src/base/io/json/Json.cpp @@ -27,6 +27,9 @@ #include "rapidjson/document.h" +#include + + namespace xmrig { static const rapidjson::Value kNullValue; @@ -36,6 +39,8 @@ static const rapidjson::Value kNullValue; bool xmrig::Json::getBool(const rapidjson::Value &obj, const char *key, bool defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsBool()) { return i->value.GetBool(); @@ -47,6 +52,8 @@ bool xmrig::Json::getBool(const rapidjson::Value &obj, const char *key, bool def const char *xmrig::Json::getString(const rapidjson::Value &obj, const char *key, const char *defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsString()) { return i->value.GetString(); @@ -58,6 +65,8 @@ const char *xmrig::Json::getString(const rapidjson::Value &obj, const char *key, const rapidjson::Value &xmrig::Json::getArray(const rapidjson::Value &obj, const char *key) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsArray()) { return i->value; @@ -69,6 +78,8 @@ const rapidjson::Value &xmrig::Json::getArray(const rapidjson::Value &obj, const const rapidjson::Value &xmrig::Json::getObject(const rapidjson::Value &obj, const char *key) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsObject()) { return i->value; @@ -80,6 +91,8 @@ const rapidjson::Value &xmrig::Json::getObject(const rapidjson::Value &obj, cons const rapidjson::Value &xmrig::Json::getValue(const rapidjson::Value &obj, const char *key) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd()) { return i->value; @@ -91,6 +104,8 @@ const rapidjson::Value &xmrig::Json::getValue(const rapidjson::Value &obj, const int xmrig::Json::getInt(const rapidjson::Value &obj, const char *key, int defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsInt()) { return i->value.GetInt(); @@ -102,6 +117,8 @@ int xmrig::Json::getInt(const rapidjson::Value &obj, const char *key, int defaul int64_t xmrig::Json::getInt64(const rapidjson::Value &obj, const char *key, int64_t defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsInt64()) { return i->value.GetInt64(); @@ -113,6 +130,8 @@ int64_t xmrig::Json::getInt64(const rapidjson::Value &obj, const char *key, int6 uint64_t xmrig::Json::getUint64(const rapidjson::Value &obj, const char *key, uint64_t defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsUint64()) { return i->value.GetUint64(); @@ -124,6 +143,8 @@ uint64_t xmrig::Json::getUint64(const rapidjson::Value &obj, const char *key, ui unsigned xmrig::Json::getUint(const rapidjson::Value &obj, const char *key, unsigned defaultValue) { + assert(obj.IsObject()); + auto i = obj.FindMember(key); if (i != obj.MemberEnd() && i->value.IsUint()) { return i->value.GetUint(); diff --git a/src/base/io/log/Log.cpp b/src/base/io/log/Log.cpp index 250bc3c4c..2cd372423 100644 --- a/src/base/io/log/Log.cpp +++ b/src/base/io/log/Log.cpp @@ -31,10 +31,10 @@ #include +#include +#include #include -#include #include -#include #include #include @@ -42,6 +42,7 @@ #include "base/io/log/Log.h" #include "base/kernel/interfaces/ILogBackend.h" #include "base/tools/Chrono.h" +#include "base/tools/Object.h" namespace xmrig { @@ -67,10 +68,10 @@ static const char *colors_map[] = { class LogPrivate { public: - inline LogPrivate() : - m_buf() - { - } + XMRIG_DISABLE_COPY_MOVE(LogPrivate) + + + LogPrivate() = default; inline ~LogPrivate() @@ -134,7 +135,7 @@ class LogPrivate const uint64_t ms = Chrono::currentMSecsSinceEpoch(); time_t now = ms / 1000; - tm stime; + tm stime{}; # ifdef _WIN32 localtime_s(&stime, &now); @@ -188,7 +189,7 @@ class LogPrivate } - char m_buf[4096]; + char m_buf[4096]{}; std::mutex m_mutex; std::vector m_backends; }; diff --git a/src/base/io/log/backends/ConsoleLog.cpp b/src/base/io/log/backends/ConsoleLog.cpp index 34a7d66ba..de907318f 100644 --- a/src/base/io/log/backends/ConsoleLog.cpp +++ b/src/base/io/log/backends/ConsoleLog.cpp @@ -47,9 +47,10 @@ xmrig::ConsoleLog::ConsoleLog() } uv_tty_set_mode(m_tty, UV_TTY_MODE_NORMAL); - m_stream = reinterpret_cast(m_tty); # ifdef WIN32 + m_stream = reinterpret_cast(m_tty); + HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); if (handle != INVALID_HANDLE_VALUE) { DWORD mode = 0; @@ -76,9 +77,6 @@ void xmrig::ConsoleLog::print(int, const char *line, size_t, size_t size, bool c # ifdef _WIN32 uv_buf_t buf = uv_buf_init(const_cast(line), static_cast(size)); -# else - uv_buf_t buf = uv_buf_init(const_cast(line), size); -# endif if (!isWritable()) { fputs(line, stdout); @@ -87,6 +85,10 @@ void xmrig::ConsoleLog::print(int, const char *line, size_t, size_t size, bool c else { uv_try_write(m_stream, &buf, 1); } +# else + fputs(line, stdout); + fflush(stdout); +# endif } @@ -97,6 +99,7 @@ bool xmrig::ConsoleLog::isSupported() const } +#ifdef WIN32 bool xmrig::ConsoleLog::isWritable() const { if (!m_stream || uv_is_writable(m_stream) != 1) { @@ -105,3 +108,4 @@ bool xmrig::ConsoleLog::isWritable() const return isSupported(); } +#endif diff --git a/src/base/io/log/backends/ConsoleLog.h b/src/base/io/log/backends/ConsoleLog.h index 6277cc7be..549243ad9 100644 --- a/src/base/io/log/backends/ConsoleLog.h +++ b/src/base/io/log/backends/ConsoleLog.h @@ -51,10 +51,14 @@ class ConsoleLog : public ILogBackend private: bool isSupported() const; + + uv_tty_t *m_tty = nullptr; + +# ifdef _WIN32 bool isWritable() const; uv_stream_t *m_stream = nullptr; - uv_tty_t *m_tty = nullptr; +# endif }; diff --git a/src/base/kernel/Base.cpp b/src/base/kernel/Base.cpp index 3740655df..90c7cb57c 100644 --- a/src/base/kernel/Base.cpp +++ b/src/base/kernel/Base.cpp @@ -23,7 +23,7 @@ */ -#include +#include #include @@ -64,15 +64,16 @@ static const char *kConfigPathV2 = "/2/config"; #endif -class xmrig::BasePrivate +namespace xmrig { + + +class BasePrivate { public: - inline BasePrivate(Process *process) : - api(nullptr), - config(nullptr), - process(process), - watcher(nullptr) - {} + XMRIG_DISABLE_COPY_MOVE_DEFAULT(BasePrivate) + + + inline BasePrivate(Process *process) : config(load(process)) {} inline ~BasePrivate() @@ -94,13 +95,33 @@ class xmrig::BasePrivate } - inline Config *load() + inline void replace(Config *newConfig) + { + Config *previousConfig = config; + config = newConfig; + + for (IBaseListener *listener : listeners) { + listener->onConfigChanged(config, previousConfig); + } + + delete previousConfig; + } + + + Api *api = nullptr; + Config *config = nullptr; + std::vector listeners; + Watcher *watcher = nullptr; + + +private: + inline Config *load(Process *process) { JsonChain chain; ConfigTransform transform; std::unique_ptr config; - transform.load(chain, process, transform); + ConfigTransform::load(chain, process, transform); if (read(chain, config)) { return config.release(); @@ -122,27 +143,10 @@ class xmrig::BasePrivate return nullptr; } +}; - inline void replace(Config *newConfig) - { - Config *previousConfig = config; - config = newConfig; - - for (IBaseListener *listener : listeners) { - listener->onConfigChanged(config, previousConfig); - } - - delete previousConfig; - } - - - Api *api; - Config *config; - Process *process; - std::vector listeners; - Watcher *watcher; -}; +} // namespace xmrig xmrig::Base::Base(Process *process) @@ -165,14 +169,6 @@ bool xmrig::Base::isReady() const int xmrig::Base::init() { - d_ptr->config = d_ptr->load(); - - if (!d_ptr->config) { - LOG_EMERG("No valid configuration found. Exiting."); - - return 1; - } - # ifdef XMRIG_FEATURE_API d_ptr->api = new Api(this); d_ptr->api->addListener(this); @@ -184,7 +180,7 @@ int xmrig::Base::init() Platform::setProcessPriority(config()->cpu().priority()); # endif - if (config()->isBackground()) { + if (isBackground()) { Log::background = true; } else { @@ -240,6 +236,12 @@ xmrig::Api *xmrig::Base::api() const } +bool xmrig::Base::isBackground() const +{ + return d_ptr->config && d_ptr->config->isBackground(); +} + + bool xmrig::Base::reload(const rapidjson::Value &json) { JsonReader reader(json); @@ -247,7 +249,7 @@ bool xmrig::Base::reload(const rapidjson::Value &json) return false; } - Config *config = new Config(); + auto config = new Config(); if (!config->read(reader, d_ptr->config->fileName())) { delete config; @@ -289,7 +291,7 @@ void xmrig::Base::onFileChanged(const String &fileName) JsonChain chain; chain.addFile(fileName); - Config *config = new Config(); + auto config = new Config(); if (!config->read(chain, chain.fileName())) { LOG_ERR("reloading failed"); diff --git a/src/base/kernel/Base.h b/src/base/kernel/Base.h index 8eb688664..ef850eddf 100644 --- a/src/base/kernel/Base.h +++ b/src/base/kernel/Base.h @@ -29,6 +29,7 @@ #include "base/api/interfaces/IApiListener.h" #include "base/kernel/interfaces/IConfigListener.h" #include "base/kernel/interfaces/IWatcherListener.h" +#include "base/tools/Object.h" #include "rapidjson/fwd.h" @@ -45,6 +46,8 @@ class Process; class Base : public IWatcherListener, public IApiListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Base) + Base(Process *process); ~Base() override; @@ -54,6 +57,7 @@ class Base : public IWatcherListener, public IApiListener virtual void stop(); Api *api() const; + bool isBackground() const; bool reload(const rapidjson::Value &json); Config *config() const; void addListener(IBaseListener *listener); diff --git a/src/base/kernel/Entry.cpp b/src/base/kernel/Entry.cpp index f9e97c2d7..1d1b7eb84 100644 --- a/src/base/kernel/Entry.cpp +++ b/src/base/kernel/Entry.cpp @@ -23,7 +23,7 @@ */ -#include +#include #include @@ -35,6 +35,11 @@ # include #endif +#ifdef XMRIG_FEATURE_OPENCL +# include "backend/opencl/wrappers/OclLib.h" +# include "backend/opencl/wrappers/OclPlatform.h" +#endif + #include "base/kernel/Entry.h" #include "base/kernel/Process.h" #include "core/config/usage.h" @@ -142,6 +147,12 @@ xmrig::Entry::Id xmrig::Entry::get(const Process &process) } # endif +# ifdef XMRIG_FEATURE_OPENCL + if (args.hasArg("--print-platforms")) { + return Platforms; + } +# endif + return Default; } @@ -150,7 +161,7 @@ int xmrig::Entry::exec(const Process &process, Id id) { switch (id) { case Usage: - printf(usage); + printf("%s\n", usage().c_str()); return 0; case Version: @@ -161,6 +172,14 @@ int xmrig::Entry::exec(const Process &process, Id id) return exportTopology(process); # endif +# ifdef XMRIG_FEATURE_OPENCL + case Platforms: + if (OclLib::init()) { + OclPlatform::print(); + } + return 0; +# endif + default: break; } diff --git a/src/base/kernel/Entry.h b/src/base/kernel/Entry.h index c0bde080d..a459410fd 100644 --- a/src/base/kernel/Entry.h +++ b/src/base/kernel/Entry.h @@ -39,7 +39,8 @@ class Entry Default, Usage, Version, - Topo + Topo, + Platforms }; static Id get(const Process &process); diff --git a/src/base/kernel/Platform.cpp b/src/base/kernel/Platform.cpp index a74f1978f..67c729236 100644 --- a/src/base/kernel/Platform.cpp +++ b/src/base/kernel/Platform.cpp @@ -23,7 +23,10 @@ */ -#include +#include "base/kernel/Platform.h" + + +#include #include @@ -33,13 +36,14 @@ #endif -#include "Platform.h" +namespace xmrig { +String Platform::m_userAgent; -xmrig::String Platform::m_userAgent; +} // namespace xmrig -void Platform::init(const char *userAgent) +void xmrig::Platform::init(const char *userAgent) { # ifdef XMRIG_FEATURE_TLS SSL_library_init(); diff --git a/src/base/kernel/Platform.h b/src/base/kernel/Platform.h index f3c2c719f..3f026f8bd 100644 --- a/src/base/kernel/Platform.h +++ b/src/base/kernel/Platform.h @@ -26,12 +26,15 @@ #define XMRIG_PLATFORM_H -#include +#include #include "base/tools/String.h" +namespace xmrig { + + class Platform { public: @@ -56,8 +59,11 @@ class Platform private: static char *createUserAgent(); - static xmrig::String m_userAgent; + static String m_userAgent; }; +} // namespace xmrig + + #endif /* XMRIG_PLATFORM_H */ diff --git a/src/base/kernel/Platform_hwloc.cpp b/src/base/kernel/Platform_hwloc.cpp new file mode 100644 index 000000000..f4b46ba1e --- /dev/null +++ b/src/base/kernel/Platform_hwloc.cpp @@ -0,0 +1,49 @@ +/* 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 2018-2019 SChernykh + * Copyright 2016-2019 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 "base/kernel/Platform.h" +#include "backend/cpu/platform/HwlocCpuInfo.h" +#include "backend/cpu/Cpu.h" + + +#include + + +bool xmrig::Platform::setThreadAffinity(uint64_t cpu_id) +{ + auto cpu = static_cast(Cpu::info()); + hwloc_obj_t pu = hwloc_get_pu_obj_by_os_index(cpu->topology(), static_cast(cpu_id)); + + if (pu == nullptr) { + return false; + } + + if (hwloc_set_cpubind(cpu->topology(), pu->cpuset, HWLOC_CPUBIND_THREAD | HWLOC_CPUBIND_STRICT) >= 0) { + return true; + } + + return hwloc_set_cpubind(cpu->topology(), pu->cpuset, HWLOC_CPUBIND_THREAD) >= 0; +} diff --git a/src/base/kernel/Platform_mac.cpp b/src/base/kernel/Platform_mac.cpp index 4e4aa0ad1..146dd52d7 100644 --- a/src/base/kernel/Platform_mac.cpp +++ b/src/base/kernel/Platform_mac.cpp @@ -30,7 +30,7 @@ #include -#include "Platform.h" +#include "base/kernel/Platform.h" #include "version.h" #ifdef XMRIG_NVIDIA_PROJECT @@ -38,7 +38,7 @@ #endif -char *Platform::createUserAgent() +char *xmrig::Platform::createUserAgent() { constexpr const size_t max = 256; @@ -60,7 +60,8 @@ char *Platform::createUserAgent() } -bool Platform::setThreadAffinity(uint64_t cpu_id) +#ifndef XMRIG_FEATURE_HWLOC +bool xmrig::Platform::setThreadAffinity(uint64_t cpu_id) { thread_port_t mach_thread; thread_affinity_policy_data_t policy = { static_cast(cpu_id) }; @@ -68,25 +69,26 @@ bool Platform::setThreadAffinity(uint64_t cpu_id) return thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, 1) == KERN_SUCCESS; } +#endif -uint32_t Platform::setTimerResolution(uint32_t resolution) +uint32_t xmrig::Platform::setTimerResolution(uint32_t resolution) { return resolution; } -void Platform::restoreTimerResolution() +void xmrig::Platform::restoreTimerResolution() { } -void Platform::setProcessPriority(int priority) +void xmrig::Platform::setProcessPriority(int priority) { } -void Platform::setThreadPriority(int priority) +void xmrig::Platform::setThreadPriority(int priority) { if (priority == -1) { return; diff --git a/src/base/kernel/Platform_unix.cpp b/src/base/kernel/Platform_unix.cpp index 3066630ae..bbba39f90 100644 --- a/src/base/kernel/Platform_unix.cpp +++ b/src/base/kernel/Platform_unix.cpp @@ -39,7 +39,7 @@ #include -#include "Platform.h" +#include "base/kernel/Platform.h" #include "version.h" #ifdef XMRIG_NVIDIA_PROJECT @@ -52,7 +52,7 @@ typedef cpuset_t cpu_set_t; #endif -char *Platform::createUserAgent() +char *xmrig::Platform::createUserAgent() { constexpr const size_t max = 256; @@ -84,7 +84,8 @@ char *Platform::createUserAgent() } -bool Platform::setThreadAffinity(uint64_t cpu_id) +#ifndef XMRIG_FEATURE_HWLOC +bool xmrig::Platform::setThreadAffinity(uint64_t cpu_id) { cpu_set_t mn; CPU_ZERO(&mn); @@ -96,25 +97,26 @@ bool Platform::setThreadAffinity(uint64_t cpu_id) return sched_setaffinity(gettid(), sizeof(cpu_set_t), &mn) == 0; # endif } +#endif -uint32_t Platform::setTimerResolution(uint32_t resolution) +uint32_t xmrig::Platform::setTimerResolution(uint32_t resolution) { return resolution; } -void Platform::restoreTimerResolution() +void xmrig::Platform::restoreTimerResolution() { } -void Platform::setProcessPriority(int priority) +void xmrig::Platform::setProcessPriority(int priority) { } -void Platform::setThreadPriority(int priority) +void xmrig::Platform::setThreadPriority(int priority) { if (priority == -1) { return; diff --git a/src/base/kernel/Platform_win.cpp b/src/base/kernel/Platform_win.cpp index f2363cd0d..064c8352f 100644 --- a/src/base/kernel/Platform_win.cpp +++ b/src/base/kernel/Platform_win.cpp @@ -29,8 +29,8 @@ #include +#include "base/kernel/Platform.h" #include "base/io/log/Log.h" -#include "Platform.h" #include "version.h" @@ -51,10 +51,10 @@ static inline OSVERSIONINFOEX winOsVersion() HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); if (ntdll ) { - RtlGetVersionFunction pRtlGetVersion = reinterpret_cast(GetProcAddress(ntdll, "RtlGetVersion")); + auto pRtlGetVersion = reinterpret_cast(GetProcAddress(ntdll, "RtlGetVersion")); if (pRtlGetVersion) { - pRtlGetVersion((LPOSVERSIONINFO) &result); + pRtlGetVersion(reinterpret_cast(&result)); } } @@ -62,7 +62,7 @@ static inline OSVERSIONINFOEX winOsVersion() } -char *Platform::createUserAgent() +char *xmrig::Platform::createUserAgent() { const auto osver = winOsVersion(); constexpr const size_t max = 256; @@ -91,7 +91,8 @@ char *Platform::createUserAgent() } -bool Platform::setThreadAffinity(uint64_t cpu_id) +#ifndef XMRIG_FEATURE_HWLOC +bool xmrig::Platform::setThreadAffinity(uint64_t cpu_id) { if (cpu_id >= 64) { LOG_ERR("Unable to set affinity. Windows supports only affinity up to 63."); @@ -99,9 +100,10 @@ bool Platform::setThreadAffinity(uint64_t cpu_id) return SetThreadAffinityMask(GetCurrentThread(), 1ULL << cpu_id) != 0; } +#endif -uint32_t Platform::setTimerResolution(uint32_t resolution) +uint32_t xmrig::Platform::setTimerResolution(uint32_t resolution) { # ifdef XMRIG_AMD_PROJECT TIMECAPS tc; @@ -119,7 +121,7 @@ uint32_t Platform::setTimerResolution(uint32_t resolution) } -void Platform::restoreTimerResolution() +void xmrig::Platform::restoreTimerResolution() { # ifdef XMRIG_AMD_PROJECT if (timerResolution) { @@ -129,7 +131,7 @@ void Platform::restoreTimerResolution() } -void Platform::setProcessPriority(int priority) +void xmrig::Platform::setProcessPriority(int priority) { if (priority == -1) { return; @@ -166,7 +168,7 @@ void Platform::setProcessPriority(int priority) } -void Platform::setThreadPriority(int priority) +void xmrig::Platform::setThreadPriority(int priority) { if (priority == -1) { return; diff --git a/src/base/kernel/Process.cpp b/src/base/kernel/Process.cpp index 9193d378e..fae0d6794 100644 --- a/src/base/kernel/Process.cpp +++ b/src/base/kernel/Process.cpp @@ -23,8 +23,8 @@ */ +#include #include -#include #include "base/kernel/Process.h" @@ -55,11 +55,6 @@ xmrig::Process::Process(int argc, char **argv) : } -xmrig::Process::~Process() -{ -} - - xmrig::String xmrig::Process::location(Location location, const char *fileName) const { constexpr const size_t max = 520; diff --git a/src/base/kernel/Process.h b/src/base/kernel/Process.h index 9b29eb57f..22959044b 100644 --- a/src/base/kernel/Process.h +++ b/src/base/kernel/Process.h @@ -47,7 +47,6 @@ class Process # endif Process(int argc, char **argv); - ~Process(); String location(Location location, const char *fileName = nullptr) const; diff --git a/src/base/kernel/config/BaseConfig.h b/src/base/kernel/config/BaseConfig.h index b58c47b6c..2e10c3ff8 100644 --- a/src/base/kernel/config/BaseConfig.h +++ b/src/base/kernel/config/BaseConfig.h @@ -56,7 +56,6 @@ class BaseConfig : public IConfig inline const String &apiId() const { return m_apiId; } inline const String &apiWorkerId() const { return m_apiWorkerId; } inline uint32_t printTime() const { return m_printTime; } - inline uint32_t version() const { return m_version; } inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); } inline const String &fileName() const override { return m_fileName; } diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index 7090b6b73..ccf5ccf11 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -23,7 +23,7 @@ */ -#include +#include #ifdef _MSC_VER @@ -51,12 +51,7 @@ static const char *kCoin = "coin"; static const char *kHttp = "http"; static const char *kPools = "pools"; -} - - -xmrig::BaseTransform::BaseTransform() -{ -} +} // namespace xmrig void xmrig::BaseTransform::load(JsonChain &chain, Process *process, IConfigTransform &transform) @@ -69,7 +64,7 @@ void xmrig::BaseTransform::load(JsonChain &chain, Process *process, IConfigTrans Document doc(kObjectType); - while (1) { + while (true) { key = getopt_long(argc, argv, short_options, options, nullptr); if (key < 0) { break; @@ -117,6 +112,10 @@ void xmrig::BaseTransform::finalize(rapidjson::Document &doc) } } } + + if (m_http) { + set(doc, kHttp, "enabled", true); + } } @@ -184,13 +183,18 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch case IConfig::FingerprintKey: /* --tls-fingerprint */ return add(doc, kPools, "tls-fingerprint", arg); + case IConfig::SelfSelectKey: /* --self-select */ + return add(doc, kPools, "self-select", arg); + case IConfig::LogFileKey: /* --log-file */ return set(doc, "log-file", arg); case IConfig::HttpAccessTokenKey: /* --http-access-token */ + m_http = true; return set(doc, kHttp, "access-token", arg); case IConfig::HttpHostKey: /* --http-host */ + m_http = true; return set(doc, kHttp, "host", arg); case IConfig::ApiWorkerIdKey: /* --api-worker-id */ @@ -245,8 +249,10 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b case IConfig::TlsKey: /* --tls */ return add(doc, kPools, "tls", enable); +# ifdef XMRIG_FEATURE_HTTP case IConfig::DaemonKey: /* --daemon */ return add(doc, kPools, "daemon", enable); +# endif # ifndef XMRIG_PROXY_PROJECT case IConfig::NicehashKey: /* --nicehash */ @@ -257,10 +263,12 @@ void xmrig::BaseTransform::transformBoolean(rapidjson::Document &doc, int key, b return set(doc, "colors", enable); case IConfig::HttpRestrictedKey: /* --http-no-restricted */ + m_http = true; return set(doc, kHttp, "restricted", enable); case IConfig::HttpEnabledKey: /* --http-enabled */ - return set(doc, kHttp, "enabled", enable); + m_http = true; + break; case IConfig::DryRunKey: /* --dry-run */ return set(doc, "dry-run", enable); @@ -287,13 +295,16 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui return set(doc, "donate-over-proxy", arg); case IConfig::HttpPort: /* --http-port */ + m_http = true; return set(doc, kHttp, "port", arg); case IConfig::PrintTimeKey: /* --print-time */ return set(doc, "print-time", arg); +# ifdef XMRIG_FEATURE_HTTP case IConfig::DaemonPollKey: /* --daemon-poll-interval */ return add(doc, kPools, "daemon-poll-interval", arg); +# endif default: break; diff --git a/src/base/kernel/config/BaseTransform.h b/src/base/kernel/config/BaseTransform.h index ab83a63f5..704f08993 100644 --- a/src/base/kernel/config/BaseTransform.h +++ b/src/base/kernel/config/BaseTransform.h @@ -45,8 +45,6 @@ class Process; class BaseTransform : public IConfigTransform { public: - BaseTransform(); - static void load(JsonChain &chain, Process *process, IConfigTransform &transform); protected: @@ -106,6 +104,8 @@ class BaseTransform : public IConfigTransform private: void transformBoolean(rapidjson::Document &doc, int key, bool enable); void transformUint64(rapidjson::Document &doc, int key, uint64_t arg); + + bool m_http = false; }; diff --git a/src/base/kernel/interfaces/IClient.h b/src/base/kernel/interfaces/IClient.h index c872a37ad..db88638ad 100644 --- a/src/base/kernel/interfaces/IClient.h +++ b/src/base/kernel/interfaces/IClient.h @@ -26,7 +26,10 @@ #define XMRIG_ICLIENT_H -#include +#include "rapidjson/fwd.h" + + +#include namespace xmrig { @@ -51,31 +54,35 @@ class IClient EXT_MAX }; - virtual ~IClient() = default; + using Callback = std::function; - virtual bool disconnect() = 0; - virtual bool hasExtension(Extension extension) const noexcept = 0; - virtual bool isEnabled() const = 0; - virtual bool isTLS() const = 0; - virtual const char *mode() const = 0; - virtual const char *tlsFingerprint() const = 0; - virtual const char *tlsVersion() const = 0; - virtual const Job &job() const = 0; - virtual const Pool &pool() const = 0; - virtual const String &ip() const = 0; - virtual int id() const = 0; - virtual int64_t submit(const JobResult &result) = 0; - virtual void connect() = 0; - virtual void connect(const Pool &pool) = 0; - virtual void deleteLater() = 0; - virtual void setAlgo(const Algorithm &algo) = 0; - virtual void setEnabled(bool enabled) = 0; - virtual void setPool(const Pool &pool) = 0; - virtual void setQuiet(bool quiet) = 0; - virtual void setRetries(int retries) = 0; - virtual void setRetryPause(uint64_t ms) = 0; - virtual void tick(uint64_t now) = 0; + virtual ~IClient() = default; + virtual bool disconnect() = 0; + virtual bool hasExtension(Extension extension) const noexcept = 0; + virtual bool isEnabled() const = 0; + virtual bool isTLS() const = 0; + virtual const char *mode() const = 0; + virtual const char *tlsFingerprint() const = 0; + virtual const char *tlsVersion() const = 0; + virtual const Job &job() const = 0; + virtual const Pool &pool() const = 0; + virtual const String &ip() const = 0; + virtual int id() const = 0; + virtual int64_t send(const rapidjson::Value &obj, Callback callback) = 0; + virtual int64_t send(const rapidjson::Value &obj) = 0; + virtual int64_t sequence() const = 0; + virtual int64_t submit(const JobResult &result) = 0; + virtual void connect() = 0; + virtual void connect(const Pool &pool) = 0; + virtual void deleteLater() = 0; + virtual void setAlgo(const Algorithm &algo) = 0; + virtual void setEnabled(bool enabled) = 0; + virtual void setPool(const Pool &pool) = 0; + virtual void setQuiet(bool quiet) = 0; + virtual void setRetries(int retries) = 0; + virtual void setRetryPause(uint64_t ms) = 0; + virtual void tick(uint64_t now) = 0; }; diff --git a/src/base/kernel/interfaces/IClientListener.h b/src/base/kernel/interfaces/IClientListener.h index 3583be5ad..45b0bcfd2 100644 --- a/src/base/kernel/interfaces/IClientListener.h +++ b/src/base/kernel/interfaces/IClientListener.h @@ -26,7 +26,7 @@ #define XMRIG_ICLIENTLISTENER_H -#include +#include #include "rapidjson/fwd.h" diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 52aed25fc..9f8d96180 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -72,6 +72,7 @@ class IConfig ProxyDonateKey = 1017, DaemonKey = 1018, DaemonPollKey = 1019, + SelfSelectKey = 1028, // xmrig common CPUPriorityKey = 1021, @@ -79,6 +80,7 @@ class IConfig PrintTimeKey = 1007, // xmrig cpu + CPUKey = 1024, AVKey = 'v', CPUAffinityKey = 1020, DryRunKey = 5000, @@ -87,6 +89,8 @@ class IConfig AssemblyKey = 1015, RandomXInitKey = 1022, RandomXNumaKey = 1023, + CPUMaxThreadsKey = 1026, + MemoryPoolKey = 1027, // xmrig amd OclPlatformKey = 1400, @@ -100,6 +104,7 @@ class IConfig OclMemChunkKey = 1408, OclUnrollKey = 1409, OclCompModeKey = 1410, + OclKey = 1411, // xmrig-proxy AccessLogFileKey = 'A', diff --git a/src/base/net/http/HttpClient.cpp b/src/base/net/http/HttpClient.cpp index 113e2f139..2699e6631 100644 --- a/src/base/net/http/HttpClient.cpp +++ b/src/base/net/http/HttpClient.cpp @@ -78,9 +78,7 @@ class ClientWriteBaton : public Baton xmrig::HttpClient::HttpClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size) : - HttpContext(HTTP_RESPONSE, listener), - m_quiet(false), - m_port(0) + HttpContext(HTTP_RESPONSE, listener) { this->method = method; this->url = url; @@ -127,7 +125,7 @@ void xmrig::HttpClient::onResolved(const Dns &dns, int status) sockaddr *addr = dns.get().addr(m_port); - uv_connect_t *req = new uv_connect_t; + auto req = new uv_connect_t; req->data = this; uv_tcp_connect(req, m_tcp, addr, onConnect); @@ -140,7 +138,7 @@ void xmrig::HttpClient::handshake() headers.insert({ "Connection", "close" }); headers.insert({ "User-Agent", Platform::userAgent() }); - if (body.size()) { + if (!body.empty()) { headers.insert({ "Content-Length", std::to_string(body.size()) }); } @@ -169,14 +167,14 @@ void xmrig::HttpClient::read(const char *data, size_t size) void xmrig::HttpClient::write(const std::string &header) { - ClientWriteBaton *baton = new ClientWriteBaton(header, std::move(body)); + auto baton = new ClientWriteBaton(header, std::move(body)); uv_write(&baton->req, stream(), baton->bufs, baton->count(), ClientWriteBaton::onWrite); } void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) { - HttpClient *client = static_cast(req->data); + auto client = static_cast(req->data); if (!client) { delete req; return; @@ -205,7 +203,7 @@ void xmrig::HttpClient::onConnect(uv_connect_t *req, int status) }, [](uv_stream_t *tcp, ssize_t nread, const uv_buf_t *buf) { - HttpClient *client = static_cast(tcp->data); + auto client = static_cast(tcp->data); if (nread >= 0) { client->read(buf->base, static_cast(nread)); diff --git a/src/base/net/http/HttpClient.h b/src/base/net/http/HttpClient.h index c5dfc43d9..acf873dc7 100644 --- a/src/base/net/http/HttpClient.h +++ b/src/base/net/http/HttpClient.h @@ -30,6 +30,7 @@ #include "base/net/http/HttpContext.h" #include "base/kernel/interfaces/IDnsListener.h" +#include "base/tools/Object.h" namespace xmrig { @@ -41,6 +42,8 @@ class String; class HttpClient : public HttpContext, public IDnsListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(HttpClient); + HttpClient(int method, const String &url, IHttpListener *listener, const char *data = nullptr, size_t size = 0); ~HttpClient() override; @@ -57,13 +60,13 @@ class HttpClient : public HttpContext, public IDnsListener virtual void read(const char *data, size_t size); virtual void write(const std::string &header); - bool m_quiet; + bool m_quiet = false; private: static void onConnect(uv_connect_t *req, int status); Dns *m_dns; - uint16_t m_port; + uint16_t m_port = 0; }; diff --git a/src/base/net/http/HttpContext.cpp b/src/base/net/http/HttpContext.cpp index e97f989b2..1130d12c5 100644 --- a/src/base/net/http/HttpContext.cpp +++ b/src/base/net/http/HttpContext.cpp @@ -136,7 +136,7 @@ void xmrig::HttpContext::closeAll() int xmrig::HttpContext::onHeaderField(http_parser *parser, const char *at, size_t length) { - HttpContext *ctx = static_cast(parser->data); + auto ctx = static_cast(parser->data); if (ctx->m_wasHeaderValue) { if (!ctx->m_lastHeaderField.empty()) { @@ -155,7 +155,7 @@ int xmrig::HttpContext::onHeaderField(http_parser *parser, const char *at, size_ int xmrig::HttpContext::onHeaderValue(http_parser *parser, const char *at, size_t length) { - HttpContext *ctx = static_cast(parser->data); + auto ctx = static_cast(parser->data); if (!ctx->m_wasHeaderValue) { ctx->m_lastHeaderValue = std::string(at, length); @@ -185,7 +185,7 @@ void xmrig::HttpContext::attach(http_parser_settings *settings) settings->on_header_value = onHeaderValue; settings->on_headers_complete = [](http_parser* parser) -> int { - HttpContext *ctx = static_cast(parser->data); + auto ctx = static_cast(parser->data); ctx->status = parser->status_code; if (parser->type == HTTP_REQUEST) { @@ -208,7 +208,7 @@ void xmrig::HttpContext::attach(http_parser_settings *settings) settings->on_message_complete = [](http_parser *parser) -> int { - HttpContext *ctx = static_cast(parser->data); + auto ctx = static_cast(parser->data); ctx->m_listener->onHttpData(*ctx); ctx->m_listener = nullptr; diff --git a/src/base/net/http/HttpContext.h b/src/base/net/http/HttpContext.h index fbb453aa9..ba4418b61 100644 --- a/src/base/net/http/HttpContext.h +++ b/src/base/net/http/HttpContext.h @@ -28,15 +28,16 @@ #define XMRIG_HTTPCONTEXT_H -typedef struct http_parser http_parser; -typedef struct http_parser_settings http_parser_settings; -typedef struct uv_connect_s uv_connect_t; -typedef struct uv_handle_s uv_handle_t; -typedef struct uv_stream_s uv_stream_t; -typedef struct uv_tcp_s uv_tcp_t; +using http_parser = struct http_parser; +using http_parser_settings = struct http_parser_settings; +using uv_connect_t = struct uv_connect_s; +using uv_handle_t = struct uv_handle_s; +using uv_stream_t = struct uv_stream_s; +using uv_tcp_t = struct uv_tcp_s; #include "base/net/http/HttpData.h" +#include "base/tools/Object.h" namespace xmrig { @@ -48,6 +49,8 @@ class IHttpListener; class HttpContext : public HttpData { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(HttpContext) + HttpContext(int parser_type, IHttpListener *listener); virtual ~HttpContext(); diff --git a/src/base/net/http/HttpsClient.cpp b/src/base/net/http/HttpsClient.cpp index 2c2873309..747aeb31f 100644 --- a/src/base/net/http/HttpsClient.cpp +++ b/src/base/net/http/HttpsClient.cpp @@ -24,7 +24,7 @@ */ -#include +#include #include #include diff --git a/src/base/net/http/HttpsClient.h b/src/base/net/http/HttpsClient.h index c6a228099..a0de150e5 100644 --- a/src/base/net/http/HttpsClient.h +++ b/src/base/net/http/HttpsClient.h @@ -28,10 +28,10 @@ #define XMRIG_HTTPSCLIENT_H -typedef struct bio_st BIO; -typedef struct ssl_ctx_st SSL_CTX; -typedef struct ssl_st SSL; -typedef struct x509_st X509; +using BIO = struct bio_st; +using SSL_CTX = struct ssl_ctx_st; +using SSL = struct ssl_st; +using X509 = struct x509_st; #include "base/net/http/HttpClient.h" @@ -44,6 +44,8 @@ namespace xmrig { class HttpsClient : public HttpClient { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(HttpsClient) + HttpsClient(int method, const String &url, IHttpListener *listener, const char *data, size_t size, const String &fingerprint); ~HttpsClient() override; diff --git a/src/base/net/stratum/BaseClient.cpp b/src/base/net/stratum/BaseClient.cpp index 325fce1c8..56e5ad7c5 100644 --- a/src/base/net/stratum/BaseClient.cpp +++ b/src/base/net/stratum/BaseClient.cpp @@ -26,6 +26,7 @@ #include "base/kernel/interfaces/IClientListener.h" #include "base/net/stratum/BaseClient.h" #include "base/net/stratum/SubmitResult.h" +#include "rapidjson/document.h" namespace xmrig { @@ -36,18 +37,38 @@ int64_t BaseClient::m_sequence = 1; xmrig::BaseClient::BaseClient(int id, IClientListener *listener) : - m_quiet(false), m_listener(listener), - m_id(id), - m_retries(5), - m_failures(0), - m_state(UnconnectedState), - m_retryPause(5000), - m_enabled(true) + m_id(id) { } +bool xmrig::BaseClient::handleResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error) +{ + if (id == 1) { + return false; + } + + auto it = m_callbacks.find(id); + if (it != m_callbacks.end()) { + const uint64_t elapsed = Chrono::steadyMSecs() - it->second.ts; + + if (error.IsObject()) { + it->second.callback(error, false, elapsed); + } + else { + it->second.callback(result, true, elapsed); + } + + m_callbacks.erase(it); + + return true; + } + + return false; +} + + bool xmrig::BaseClient::handleSubmitResponse(int64_t id, const char *error) { auto it = m_results.find(id); diff --git a/src/base/net/stratum/BaseClient.h b/src/base/net/stratum/BaseClient.h index 56bdc1263..974e61a5e 100644 --- a/src/base/net/stratum/BaseClient.h +++ b/src/base/net/stratum/BaseClient.h @@ -32,6 +32,7 @@ #include "base/kernel/interfaces/IClient.h" #include "base/net/stratum/Job.h" #include "base/net/stratum/Pool.h" +#include "base/tools/Chrono.h" namespace xmrig { @@ -46,11 +47,13 @@ class BaseClient : public IClient public: BaseClient(int id, IClientListener *listener); +protected: inline bool isEnabled() const override { return m_enabled; } inline const Job &job() const override { return m_job; } inline const Pool &pool() const override { return m_pool; } inline const String &ip() const override { return m_ip; } inline int id() const override { return m_id; } + inline int64_t sequence() const override { return m_sequence; } inline void setAlgo(const Algorithm &algo) override { m_pool.setAlgo(algo); } inline void setEnabled(bool enabled) override { m_enabled = enabled; } inline void setPool(const Pool &pool) override { if (pool.isValid()) { m_pool = pool; } } @@ -68,26 +71,36 @@ class BaseClient : public IClient ReconnectingState }; + struct SendResult + { + inline SendResult(Callback &&callback) : callback(callback), ts(Chrono::steadyMSecs()) {} + + Callback callback; + const uint64_t ts; + }; + inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; } + bool handleResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); bool handleSubmitResponse(int64_t id, const char *error = nullptr); - bool m_quiet; + bool m_quiet = false; IClientListener *m_listener; int m_id; - int m_retries; - int64_t m_failures; + int m_retries = 5; + int64_t m_failures = 0; Job m_job; Pool m_pool; - SocketState m_state; + SocketState m_state = UnconnectedState; + std::map m_callbacks; std::map m_results; String m_ip; - uint64_t m_retryPause; + uint64_t m_retryPause = 5000; static int64_t m_sequence; private: - bool m_enabled; + bool m_enabled = true; }; diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index b9189247f..3619e4e9f 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018-2019 SChernykh + * Copyright 2019 jtgrassie * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -22,11 +23,11 @@ * along with this program. If not, see . */ -#include -#include +#include +#include #include -#include -#include +#include +#include #include @@ -136,6 +137,41 @@ const char *xmrig::Client::tlsVersion() const } +int64_t xmrig::Client::send(const rapidjson::Value &obj, Callback callback) +{ + assert(obj["id"] == sequence()); + + m_callbacks.insert({ sequence(), std::move(callback) }); + + return send(obj); +} + + +int64_t xmrig::Client::send(const rapidjson::Value &obj) +{ + using namespace rapidjson; + + Value value; + + StringBuffer buffer(nullptr, 512); + Writer writer(buffer); + obj.Accept(writer); + + const size_t size = buffer.GetSize(); + if (size > (sizeof(m_sendBuf) - 2)) { + LOG_ERR("[%s] send failed: \"send buffer overflow: %zu > %zu\"", url(), size, (sizeof(m_sendBuf) - 2)); + close(); + return -1; + } + + memcpy(m_sendBuf, buffer.GetString(), size); + m_sendBuf[size] = '\n'; + m_sendBuf[size + 1] = '\0'; + + return send(size + 1); +} + + int64_t xmrig::Client::submit(const JobResult &result) { # ifndef XMRIG_PROXY_PROJECT @@ -320,9 +356,23 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) return false; } - if (!job.setBlob(params["blob"].GetString())) { - *code = 4; - return false; +# ifdef XMRIG_FEATURE_HTTP + if (m_pool.mode() == Pool::MODE_SELF_SELECT) { + job.setExtraNonce(Json::getString(params, "extra_nonce")); + job.setPoolWallet(Json::getString(params, "pool_wallet")); + + if (job.extraNonce().isNull() || job.poolWallet().isNull()) { + *code = 4; + return false; + } + } + else +# endif + { + if (!job.setBlob(params["blob"].GetString())) { + *code = 4; + return false; + } } if (!job.setTarget(params["target"].GetString())) { @@ -345,7 +395,7 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) return false; } - if (job.algorithm().family() == Algorithm::RANDOM_X && !job.setSeedHash(Json::getString(params, "seed_hash"))) { + if (m_pool.mode() != Pool::MODE_SELF_SELECT && job.algorithm().family() == Algorithm::RANDOM_X && !job.setSeedHash(Json::getString(params, "seed_hash"))) { if (!isQuiet()) { LOG_ERR("[%s] failed to parse field \"seed_hash\" required by RandomX", url(), algo); } @@ -473,29 +523,6 @@ int xmrig::Client::resolve(const String &host) } -int64_t xmrig::Client::send(const rapidjson::Document &doc) -{ - using namespace rapidjson; - - StringBuffer buffer(nullptr, 512); - Writer writer(buffer); - doc.Accept(writer); - - const size_t size = buffer.GetSize(); - if (size > (sizeof(m_sendBuf) - 2)) { - LOG_ERR("[%s] send failed: \"send buffer overflow: %zu > %zu\"", url(), size, (sizeof(m_sendBuf) - 2)); - close(); - return -1; - } - - memcpy(m_sendBuf, buffer.GetString(), size); - m_sendBuf[size] = '\n'; - m_sendBuf[size + 1] = '\0'; - - return send(size + 1); -} - - int64_t xmrig::Client::send(size_t size) { LOG_DEBUG("[%s] send (%d bytes): \"%.*s\"", url(), size, static_cast(size) - 1, m_sendBuf); @@ -719,6 +746,10 @@ void xmrig::Client::parseNotification(const char *method, const rapidjson::Value void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error) { + if (handleResponse(id, result, error)) { + return; + } + if (error.IsObject()) { const char *message = error["message"].GetString(); @@ -908,8 +939,14 @@ void xmrig::Client::onConnect(uv_connect_t *req, int status) LOG_ERR("[%s] connect error: \"%s\"", client->url(), uv_strerror(status)); } + if (client->state() == ReconnectingState) { + return; + } + if (client->state() != ConnectingState) { - LOG_ERR("[%s] connect error: \"invalid state: %d\"", client->url(), client->state()); + if (!client->isQuiet()) { + LOG_ERR("[%s] connect error: \"invalid state: %d\"", client->url(), client->state()); + } return; } diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index ff2bf7f6a..da4234845 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2018-2019 SChernykh + * Copyright 2019 jtgrassie * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -40,10 +41,11 @@ #include "base/net/stratum/SubmitResult.h" #include "base/net/tools/RecvBuf.h" #include "base/net/tools/Storage.h" +#include "base/tools/Object.h" #include "crypto/common/Algorithm.h" -typedef struct bio_st BIO; +using BIO = struct bio_st; namespace xmrig { @@ -56,6 +58,8 @@ class JobResult; class Client : public BaseClient, public IDnsListener, public ILineListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Client) + constexpr static uint64_t kConnectTimeout = 20 * 1000; constexpr static uint64_t kResponseTimeout = 20 * 1000; @@ -73,6 +77,8 @@ class Client : public BaseClient, public IDnsListener, public ILineListener bool isTLS() const override; const char *tlsFingerprint() const override; const char *tlsVersion() const override; + int64_t send(const rapidjson::Value &obj, Callback callback) override; + int64_t send(const rapidjson::Value &obj) override; int64_t submit(const JobResult &result) override; void connect() override; void connect(const Pool &pool) override; @@ -95,7 +101,6 @@ class Client : public BaseClient, public IDnsListener, public ILineListener bool send(BIO *bio); bool verifyAlgorithm(const Algorithm &algorithm, const char *algo) const; int resolve(const String &host); - int64_t send(const rapidjson::Document &doc); int64_t send(size_t size); void connect(sockaddr *addr); void handshake(); diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index 00b62e39a..e819c07d6 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -27,9 +27,10 @@ #define XMRIG_DAEMONCLIENT_H -#include "base/net/stratum/BaseClient.h" -#include "base/kernel/interfaces/ITimerListener.h" #include "base/kernel/interfaces/IHttpListener.h" +#include "base/kernel/interfaces/ITimerListener.h" +#include "base/net/stratum/BaseClient.h" +#include "base/tools/Object.h" namespace xmrig { @@ -38,6 +39,8 @@ namespace xmrig { class DaemonClient : public BaseClient, public ITimerListener, public IHttpListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(DaemonClient) + DaemonClient(int id, IClientListener *listener); ~DaemonClient() override; @@ -51,12 +54,14 @@ class DaemonClient : public BaseClient, public ITimerListener, public IHttpListe void onHttpData(const HttpData &data) override; void onTimer(const Timer *timer) override; - inline bool hasExtension(Extension) const noexcept override { return false; } - inline const char *mode() const override { return "daemon"; } - inline const char *tlsFingerprint() const override { return m_tlsFingerprint; } - inline const char *tlsVersion() const override { return m_tlsVersion; } - inline void deleteLater() override { delete this; } - inline void tick(uint64_t) override {} + inline bool hasExtension(Extension) const noexcept override { return false; } + inline const char *mode() const override { return "daemon"; } + inline const char *tlsFingerprint() const override { return m_tlsFingerprint; } + inline const char *tlsVersion() const override { return m_tlsVersion; } + inline int64_t send(const rapidjson::Value &, Callback) override { return -1; } + inline int64_t send(const rapidjson::Value &) override { return -1; } + inline void deleteLater() override { delete this; } + inline void tick(uint64_t) override {} private: bool isOutdated(uint64_t height, const char *hash) const; diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index 04bd82d87..ef1b03b59 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -25,32 +25,18 @@ */ -#include -#include +#include +#include #include "base/net/stratum/Job.h" #include "base/tools/Buffer.h" -xmrig::Job::Job() : - m_blob(), - m_seedHash() -{ -} - - xmrig::Job::Job(bool nicehash, const Algorithm &algorithm, const String &clientId) : m_algorithm(algorithm), m_nicehash(nicehash), - m_clientId(clientId), - m_blob(), - m_seedHash() -{ -} - - -xmrig::Job::~Job() + m_clientId(clientId) { } @@ -96,7 +82,7 @@ bool xmrig::Job::setBlob(const char *blob) bool xmrig::Job::setSeedHash(const char *hash) { - if (!hash || (strlen(hash) != sizeof(m_seedHash) * 2)) { + if (!hash || (strlen(hash) != kMaxSeedSize * 2)) { return false; } @@ -104,7 +90,9 @@ bool xmrig::Job::setSeedHash(const char *hash) m_rawSeedHash = hash; # endif - return Buffer::fromHex(hash, sizeof(m_seedHash) * 2, m_seedHash); + m_seed = Buffer::fromHex(hash, kMaxSeedSize * 2); + + return !m_seed.isEmpty(); } @@ -164,18 +152,20 @@ void xmrig::Job::setDiff(uint64_t diff) void xmrig::Job::copy(const Job &other) { - m_algorithm = other.m_algorithm; - m_nicehash = other.m_nicehash; - m_size = other.m_size; - m_clientId = other.m_clientId; - m_id = other.m_id; - m_diff = other.m_diff; - m_height = other.m_height; - m_target = other.m_target; - m_index = other.m_index; + m_algorithm = other.m_algorithm; + m_nicehash = other.m_nicehash; + m_size = other.m_size; + m_clientId = other.m_clientId; + m_id = other.m_id; + m_diff = other.m_diff; + m_height = other.m_height; + m_target = other.m_target; + m_index = other.m_index; + m_seed = other.m_seed; + m_extraNonce = other.m_extraNonce; + m_poolWallet = other.m_poolWallet; memcpy(m_blob, other.m_blob, sizeof(m_blob)); - memcpy(m_seedHash, other.m_seedHash, sizeof(m_seedHash)); # ifdef XMRIG_PROXY_PROJECT m_rawSeedHash = other.m_rawSeedHash; diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index a1a3b611a..3c4c4724c 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -28,10 +28,11 @@ #define XMRIG_JOB_H -#include -#include +#include +#include +#include "base/tools/Buffer.h" #include "base/tools/String.h" #include "crypto/common/Algorithm.h" @@ -45,10 +46,11 @@ class Job // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk. // SECOR increase requirements for blob size: https://github.com/xmrig/xmrig/issues/913 static constexpr const size_t kMaxBlobSize = 128; + static constexpr const size_t kMaxSeedSize = 32; - Job(); + Job() = default; Job(bool nicehash, const Algorithm &algorithm, const String &clientId); - ~Job(); + ~Job() = default; bool isEqual(const Job &other) const; bool setBlob(const char *blob); @@ -56,28 +58,32 @@ class Job bool setTarget(const char *target); void setDiff(uint64_t diff); - inline bool isNicehash() const { return m_nicehash; } - inline bool isValid() const { return m_size > 0 && m_diff > 0; } - inline bool setId(const char *id) { return m_id = id; } - inline const Algorithm &algorithm() const { return m_algorithm; } - inline const String &clientId() const { return m_clientId; } - 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 *seedHash() const { return m_seedHash; } - inline size_t size() const { return m_size; } - inline uint32_t *nonce() { return reinterpret_cast(m_blob + 39); } - inline uint64_t diff() const { return m_diff; } - inline uint64_t height() const { return m_height; } - inline uint64_t target() const { return m_target; } - inline uint8_t fixedByte() const { return *(m_blob + 42); } - inline uint8_t index() const { return m_index; } - inline void reset() { m_size = 0; m_diff = 0; } - inline void setAlgorithm(const Algorithm::Id id) { m_algorithm = id; } - inline void setAlgorithm(const char *algo) { m_algorithm = algo; } - inline void setClientId(const String &id) { m_clientId = id; } - inline void setHeight(uint64_t height) { m_height = height; } - inline void setIndex(uint8_t index) { m_index = index; } + inline bool isNicehash() const { return m_nicehash; } + inline bool isValid() const { return m_size > 0 && m_diff > 0; } + inline bool setId(const char *id) { return m_id = id; } + inline const Algorithm &algorithm() const { return m_algorithm; } + inline const Buffer &seed() const { return m_seed; } + inline const String &clientId() const { return m_clientId; } + inline const String &extraNonce() const { return m_extraNonce; } + inline const String &id() const { return m_id; } + inline const String &poolWallet() const { return m_poolWallet; } + inline const uint32_t *nonce() const { return reinterpret_cast(m_blob + 39); } + inline const uint8_t *blob() const { return m_blob; } + inline size_t size() const { return m_size; } + inline uint32_t *nonce() { return reinterpret_cast(m_blob + 39); } + inline uint64_t diff() const { return m_diff; } + inline uint64_t height() const { return m_height; } + inline uint64_t target() const { return m_target; } + inline uint8_t fixedByte() const { return *(m_blob + 42); } + inline uint8_t index() const { return m_index; } + inline void reset() { m_size = 0; m_diff = 0; } + inline void setAlgorithm(const Algorithm::Id id) { m_algorithm = id; } + inline void setAlgorithm(const char *algo) { m_algorithm = algo; } + inline void setClientId(const String &id) { m_clientId = id; } + inline void setExtraNonce(const String &extraNonce) { m_extraNonce = extraNonce; } + inline void setHeight(uint64_t height) { m_height = height; } + inline void setIndex(uint8_t index) { m_index = index; } + inline void setPoolWallet(const String &poolWallet) { m_poolWallet = poolWallet; } # ifdef XMRIG_PROXY_PROJECT inline char *rawBlob() { return m_rawBlob; } @@ -98,15 +104,17 @@ class Job Algorithm m_algorithm; bool m_nicehash = false; + Buffer m_seed; size_t m_size = 0; String m_clientId; + String m_extraNonce; String m_id; + String m_poolWallet; uint64_t m_diff = 0; uint64_t m_height = 0; uint64_t m_target = 0; - uint8_t m_blob[kMaxBlobSize]; + uint8_t m_blob[kMaxBlobSize]{ 0 }; uint8_t m_index = 0; - uint8_t m_seedHash[32]; # ifdef XMRIG_PROXY_PROJECT char m_rawBlob[kMaxBlobSize * 2 + 8]; diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index 15586fe87..eb2fe5066 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -24,24 +24,23 @@ */ -#include -#include -#include -#include +#include +#include +#include +#include -#include "base/io/json/Json.h" #include "base/net/stratum/Pool.h" +#include "base/io/json/Json.h" +#include "base/io/log/Log.h" +#include "base/kernel/Platform.h" +#include "base/net/stratum/Client.h" #include "rapidjson/document.h" -#ifdef APP_DEBUG -# include "base/io/log/Log.h" -#endif - - -#ifdef _MSC_VER -# define strncasecmp _strnicmp +#ifdef XMRIG_FEATURE_HTTP +# include "base/net/stratum/DaemonClient.h" +# include "base/net/stratum/SelfSelectClient.h" #endif @@ -57,6 +56,7 @@ static const char *kKeepalive = "keepalive"; static const char *kNicehash = "nicehash"; static const char *kPass = "pass"; static const char *kRigId = "rig-id"; +static const char *kSelfSelect = "self-select"; static const char *kTls = "tls"; static const char *kUrl = "url"; static const char *kUser = "user"; @@ -64,54 +64,23 @@ static const char *kUser = "user"; const String Pool::kDefaultPassword = "x"; const String Pool::kDefaultUser = "x"; -static const char kStratumTcp[] = "stratum+tcp://"; -static const char kStratumSsl[] = "stratum+ssl://"; - -#ifdef XMRIG_FEATURE_HTTP -static const char kDaemonHttp[] = "daemon+http://"; -static const char kDaemonHttps[] = "daemon+https://"; -#endif - } -xmrig::Pool::Pool() : - m_keepAlive(0), - m_flags(0), - m_port(kDefaultPort), - m_pollInterval(kDefaultPollInterval) -{ -} - - -/** - * @brief Parse url. - * - * Valid urls: - * example.com - * example.com:3333 - * stratum+tcp://example.com - * stratum+tcp://example.com:3333 - * - * @param url - */ xmrig::Pool::Pool(const char *url) : - m_keepAlive(0), - m_flags(1), - m_port(kDefaultPort), - m_pollInterval(kDefaultPollInterval) + m_flags(1 << FLAG_ENABLED), + m_pollInterval(kDefaultPollInterval), + m_url(url) { - parse(url); } xmrig::Pool::Pool(const rapidjson::Value &object) : - m_keepAlive(0), - m_flags(1), - m_port(kDefaultPort), - m_pollInterval(kDefaultPollInterval) + m_flags(1 << FLAG_ENABLED), + m_pollInterval(kDefaultPollInterval), + m_url(Json::getString(object, kUrl)) { - if (!parse(Json::getString(object, kUrl))) { + if (!m_url.isValid()) { return; } @@ -122,11 +91,18 @@ xmrig::Pool::Pool(const rapidjson::Value &object) : m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval); m_algorithm = Json::getString(object, kAlgo); m_coin = Json::getString(object, kCoin); + m_daemon = Json::getString(object, kSelfSelect); m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true)); m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash)); - m_flags.set(FLAG_TLS, Json::getBool(object, kTls, m_flags.test(FLAG_TLS))); - m_flags.set(FLAG_DAEMON, Json::getBool(object, kDaemon, m_flags.test(FLAG_DAEMON))); + m_flags.set(FLAG_TLS, Json::getBool(object, kTls) || m_url.isTLS()); + + if (m_daemon.isValid()) { + m_mode = MODE_SELF_SELECT; + } + else if (Json::getBool(object, kDaemon)) { + m_mode = MODE_DAEMON; + } const rapidjson::Value &keepalive = Json::getValue(object, kKeepalive); if (keepalive.IsInt()) { @@ -140,21 +116,12 @@ xmrig::Pool::Pool(const rapidjson::Value &object) : xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls) : m_keepAlive(keepAlive), - m_flags(1), - m_host(host), + m_flags(1 << FLAG_ENABLED), m_password(password), m_user(user), - m_port(port), - m_pollInterval(kDefaultPollInterval) + m_pollInterval(kDefaultPollInterval), + m_url(host, port, tls) { - const size_t size = m_host.size() + 8; - assert(size > 8); - - char *url = new char[size](); - snprintf(url, size - 1, "%s:%d", m_host.data(), m_port); - - m_url = url; - m_flags.set(FLAG_NICEHASH, nicehash); m_flags.set(FLAG_TLS, tls); } @@ -169,12 +136,18 @@ bool xmrig::Pool::isEnabled() const # endif # ifndef XMRIG_FEATURE_HTTP - if (isDaemon()) { + if (m_mode == MODE_DAEMON) { return false; } # endif - if (isDaemon() && (!algorithm().isValid() && !coin().isValid())) { +# ifndef XMRIG_FEATURE_HTTP + if (m_mode == MODE_SELF_SELECT) { + return false; + } +# endif + + if (m_mode == MODE_DAEMON && (!algorithm().isValid() && !coin().isValid())) { return false; } @@ -186,79 +159,43 @@ bool xmrig::Pool::isEqual(const Pool &other) const { return (m_flags == other.m_flags && m_keepAlive == other.m_keepAlive - && m_port == other.m_port && m_algorithm == other.m_algorithm && m_coin == other.m_coin + && m_mode == other.m_mode && m_fingerprint == other.m_fingerprint - && m_host == other.m_host && m_password == other.m_password && m_rigId == other.m_rigId && m_url == other.m_url && m_user == other.m_user && m_pollInterval == other.m_pollInterval + && m_daemon == other.m_daemon ); } -bool xmrig::Pool::parse(const char *url) +xmrig::IClient *xmrig::Pool::createClient(int id, IClientListener *listener) const { - assert(url != nullptr); - if (url == nullptr) { - return false; - } - - const char *p = strstr(url, "://"); - const char *base = url; - - if (p) { - if (strncasecmp(url, kStratumTcp, sizeof(kStratumTcp) - 1) == 0) { - m_flags.set(FLAG_DAEMON, false); - m_flags.set(FLAG_TLS, false); - } - else if (strncasecmp(url, kStratumSsl, sizeof(kStratumSsl) - 1) == 0) { - m_flags.set(FLAG_DAEMON, false); - m_flags.set(FLAG_TLS, true); - } -# ifdef XMRIG_FEATURE_HTTP - else if (strncasecmp(url, kDaemonHttps, sizeof(kDaemonHttps) - 1) == 0) { - m_flags.set(FLAG_DAEMON, true); - m_flags.set(FLAG_TLS, true); - } - else if (strncasecmp(url, kDaemonHttp, sizeof(kDaemonHttp) - 1) == 0) { - m_flags.set(FLAG_DAEMON, true); - m_flags.set(FLAG_TLS, false); - } -# endif - else { - return false; - } + IClient *client = nullptr; - base = p + 3; + if (m_mode == MODE_POOL) { + client = new Client(id, Platform::userAgent(), listener); } - - if (!strlen(base) || *base == '/') { - return false; - } - - m_url = url; - if (base[0] == '[') { - return parseIPv6(base); +# ifdef XMRIG_FEATURE_HTTP + else if (m_mode == MODE_DAEMON) { + client = new DaemonClient(id, listener); } - - const char *port = strchr(base, ':'); - if (!port) { - m_host = base; - return true; + else if (m_mode == MODE_SELF_SELECT) { + client = new SelfSelectClient(id, Platform::userAgent(), listener); } +# endif - const size_t size = static_cast(port++ - base + 1); - char *host = new char[size](); - memcpy(host, base, size - 1); + assert(client != nullptr); - m_host = host; - m_port = static_cast(strtol(port, nullptr, 10)); + if (client) { + client->setPool(*this); + } - return true; + return client; } @@ -272,10 +209,10 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const obj.AddMember(StringRef(kAlgo), m_algorithm.toJSON(), allocator); obj.AddMember(StringRef(kCoin), m_coin.toJSON(), allocator); - obj.AddMember(StringRef(kUrl), m_url.toJSON(), allocator); + obj.AddMember(StringRef(kUrl), url().toJSON(), allocator); obj.AddMember(StringRef(kUser), m_user.toJSON(), allocator); - if (!isDaemon()) { + if (m_mode != MODE_DAEMON) { obj.AddMember(StringRef(kPass), m_password.toJSON(), allocator); obj.AddMember(StringRef(kRigId), m_rigId.toJSON(), allocator); @@ -294,22 +231,44 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator); obj.AddMember(StringRef(kTls), isTLS(), allocator); obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator); - obj.AddMember(StringRef(kDaemon), m_flags.test(FLAG_DAEMON), allocator); + obj.AddMember(StringRef(kDaemon), m_mode == MODE_DAEMON, allocator); - if (isDaemon()) { + if (m_mode == MODE_DAEMON) { obj.AddMember(StringRef(kDaemonPollInterval), m_pollInterval, allocator); } + else { + obj.AddMember(StringRef(kSelfSelect), m_daemon.url().toJSON(), allocator); + } return obj; } +std::string xmrig::Pool::printableName() const +{ + std::string out(CSI "1;" + std::to_string(isEnabled() ? (isTLS() ? 32 : 36) : 31) + "m" + url().data() + CLEAR); + + if (m_coin.isValid()) { + out += std::string(" coin ") + WHITE_BOLD_S + m_coin.name() + CLEAR; + } + else { + out += std::string(" algo ") + WHITE_BOLD_S + (m_algorithm.isValid() ? m_algorithm.shortName() : "auto") + CLEAR; + } + + if (m_mode == MODE_SELF_SELECT) { + out += std::string(" self-select ") + CSI "1;" + std::to_string(m_daemon.isTLS() ? 32 : 36) + "m" + m_daemon.url().data() + CLEAR; + } + + return out; +} + + #ifdef APP_DEBUG void xmrig::Pool::print() const { - LOG_NOTICE("url: %s", m_url.data()); - LOG_DEBUG ("host: %s", m_host.data()); - LOG_DEBUG ("port: %d", static_cast(m_port)); + LOG_NOTICE("url: %s", url().data()); + LOG_DEBUG ("host: %s", host().data()); + LOG_DEBUG ("port: %d", static_cast(port())); LOG_DEBUG ("user: %s", m_user.data()); LOG_DEBUG ("pass: %s", m_password.data()); LOG_DEBUG ("rig-id %s", m_rigId.data()); @@ -318,26 +277,3 @@ void xmrig::Pool::print() const LOG_DEBUG ("keepAlive: %d", m_keepAlive); } #endif - - -bool xmrig::Pool::parseIPv6(const char *addr) -{ - const char *end = strchr(addr, ']'); - if (!end) { - return false; - } - - const char *port = strchr(end, ':'); - if (!port) { - return false; - } - - const size_t size = static_cast(end - addr); - char *host = new char[size](); - memcpy(host, addr + 1, size - 1); - - m_host = host; - m_port = static_cast(strtol(port + 1, nullptr, 10)); - - return true; -} diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index 15d31ccc7..ca375c076 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -31,7 +31,7 @@ #include -#include "base/tools/String.h" +#include "base/net/stratum/Url.h" #include "crypto/common/Coin.h" #include "rapidjson/fwd.h" @@ -39,15 +39,17 @@ namespace xmrig { +class IClient; +class IClientListener; + + class Pool { public: - enum Flags { - FLAG_ENABLED, - FLAG_NICEHASH, - FLAG_TLS, - FLAG_DAEMON, - FLAG_MAX + enum Mode { + MODE_POOL, + MODE_DAEMON, + MODE_SELF_SELECT }; static const String kDefaultPassword; @@ -57,7 +59,7 @@ class Pool constexpr static uint16_t kDefaultPort = 3333; constexpr static uint64_t kDefaultPollInterval = 1000; - Pool(); + Pool() = default; Pool(const char *url); Pool(const rapidjson::Value &object); Pool(const char *host, @@ -69,20 +71,21 @@ class Pool bool tls = false ); - inline bool isDaemon() const { return m_flags.test(FLAG_DAEMON); } inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); } inline bool isTLS() const { return m_flags.test(FLAG_TLS); } - inline bool isValid() const { return !m_host.isNull() && m_port > 0; } + inline bool isValid() const { return m_url.isValid(); } inline const Algorithm &algorithm() const { return m_algorithm; } inline const Coin &coin() const { return m_coin; } inline const String &fingerprint() const { return m_fingerprint; } - inline const String &host() const { return m_host; } + inline const String &host() const { return m_url.host(); } inline const String &password() const { return !m_password.isNull() ? m_password : kDefaultPassword; } inline const String &rigId() const { return m_rigId; } - inline const String &url() const { return m_url; } + inline const String &url() const { return m_url.url(); } inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; } + inline const Url &daemon() const { return m_daemon; } inline int keepAlive() const { return m_keepAlive; } - inline uint16_t port() const { return m_port; } + inline Mode mode() const { return m_mode; } + inline uint16_t port() const { return m_url.port(); } inline uint64_t pollInterval() const { return m_pollInterval; } inline void setAlgo(const Algorithm &algorithm) { m_algorithm = algorithm; } inline void setPassword(const String &password) { m_password = password; } @@ -94,31 +97,37 @@ class Pool bool isEnabled() const; bool isEqual(const Pool &other) const; - bool parse(const char *url); + IClient *createClient(int id, IClientListener *listener) const; rapidjson::Value toJSON(rapidjson::Document &doc) const; + std::string printableName() const; # ifdef APP_DEBUG void print() const; # endif private: + enum Flags { + FLAG_ENABLED, + FLAG_NICEHASH, + FLAG_TLS, + FLAG_MAX + }; + inline void setKeepAlive(bool enable) { setKeepAlive(enable ? kKeepAliveTimeout : 0); } inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; } - bool parseIPv6(const char *addr); - Algorithm m_algorithm; Coin m_coin; - int m_keepAlive; - std::bitset m_flags; + int m_keepAlive = 0; + Mode m_mode = MODE_POOL; + std::bitset m_flags = 0; String m_fingerprint; - String m_host; String m_password; String m_rigId; - String m_url; String m_user; - uint16_t m_port; - uint64_t m_pollInterval; + uint64_t m_pollInterval = kDefaultPollInterval; + Url m_daemon; + Url m_url; }; diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp index 600c97edb..c88e001fc 100644 --- a/src/base/net/stratum/Pools.cpp +++ b/src/base/net/stratum/Pools.cpp @@ -65,7 +65,7 @@ xmrig::IStrategy *xmrig::Pools::createStrategy(IStrategyListener *listener) cons } } - FailoverStrategy *strategy = new FailoverStrategy(retryPause(), retries(), listener); + auto strategy = new FailoverStrategy(retryPause(), retries(), listener); for (const Pool &pool : m_data) { if (pool.isEnabled()) { strategy->add(pool); @@ -135,13 +135,7 @@ void xmrig::Pools::print() const { size_t i = 1; for (const Pool &pool : m_data) { - Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " %s " WHITE_BOLD("%s"), - i, - (pool.isEnabled() ? (pool.isTLS() ? 32 : 36) : 31), - pool.url().data(), - pool.coin().isValid() ? "coin" : "algo", - pool.coin().isValid() ? pool.coin().name() : (pool.algorithm().isValid() ? pool.algorithm().shortName() : "auto") - ); + Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") "%s", i, pool.printableName().c_str()); i++; } diff --git a/src/base/net/stratum/SelfSelectClient.cpp b/src/base/net/stratum/SelfSelectClient.cpp new file mode 100644 index 000000000..4de49f6ef --- /dev/null +++ b/src/base/net/stratum/SelfSelectClient.cpp @@ -0,0 +1,306 @@ +/* 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-2019 SChernykh + * Copyright 2019 jtgrassie + * Copyright 2016-2019 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 "base/net/stratum/SelfSelectClient.h" +#include "3rdparty/http-parser/http_parser.h" +#include "base/io/json/Json.h" +#include "base/io/json/JsonRequest.h" +#include "base/io/log/Log.h" +#include "base/net/http/HttpClient.h" +#include "base/net/stratum/Client.h" +#include "rapidjson/document.h" +#include "rapidjson/error/en.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" + + +#ifdef XMRIG_FEATURE_TLS +# include "base/net/http/HttpsClient.h" +#endif + + +namespace xmrig { + +static const char *kBlob = "blob"; +static const char *kBlockhashingBlob = "blockhashing_blob"; +static const char *kBlocktemplateBlob = "blocktemplate_blob"; +static const char *kDifficulty = "difficulty"; +static const char *kHeight = "height"; +static const char *kId = "id"; +static const char *kJobId = "job_id"; +static const char *kNextSeedHash = "next_seed_hash"; +static const char *kPrevHash = "prev_hash"; +static const char *kSeedHash = "seed_hash"; + +static const char * const required_fields[] = { kBlocktemplateBlob, kBlockhashingBlob, kHeight, kDifficulty, kPrevHash }; + +} /* namespace xmrig */ + + +xmrig::SelfSelectClient::SelfSelectClient(int id, const char *agent, IClientListener *listener) : + m_listener(listener) +{ + m_client = new Client(id, agent, this); +} + + +xmrig::SelfSelectClient::~SelfSelectClient() +{ + delete m_client; +} + + +void xmrig::SelfSelectClient::tick(uint64_t now) +{ + m_client->tick(now); + + if (m_state == RetryState) { + if (Chrono::steadyMSecs() - m_timestamp < m_retryPause) { + return; + } + + getBlockTemplate(); + } +} + + +void xmrig::SelfSelectClient::onJobReceived(IClient *, const Job &job, const rapidjson::Value &) +{ + m_job = job; + + getBlockTemplate(); +} + + +void xmrig::SelfSelectClient::onLogin(IClient *, rapidjson::Document &doc, rapidjson::Value ¶ms) +{ + params.AddMember("mode", "self-select", doc.GetAllocator()); + + m_listener->onLogin(this, doc, params); +} + + +bool xmrig::SelfSelectClient::parseResponse(int64_t id, rapidjson::Value &result, const rapidjson::Value &error) +{ + if (id == -1) { + return false; + } + + if (error.IsObject()) { + LOG_ERR("[%s] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", pool().daemon().url().data(), Json::getString(error, "message"), Json::getInt(error, "code")); + + return false; + } + + if (!result.IsObject()) { + return false; + } + + for (auto field : required_fields) { + if (!result.HasMember(field)) { + LOG_ERR("[%s] required field " RED_BOLD("\"%s\"") RED_S " not found", pool().daemon().url().data(), field); + + return false; + } + } + + if (!m_job.setBlob(result[kBlockhashingBlob].GetString())) { + return false; + } + + if (pool().coin().isValid()) { + m_job.setAlgorithm(pool().coin().algorithm(m_job.blob()[0])); + } + + m_job.setHeight(Json::getUint64(result, kHeight)); + m_job.setSeedHash(Json::getString(result, kSeedHash)); + + submitBlockTemplate(result); + + return true; +} + + +void xmrig::SelfSelectClient::getBlockTemplate() +{ + setState(WaitState); + + using namespace rapidjson; + Document doc(kObjectType); + auto &allocator = doc.GetAllocator(); + + Value params(kObjectType); + params.AddMember("wallet_address", m_job.poolWallet().toJSON(), allocator); + params.AddMember("extra_nonce", m_job.extraNonce().toJSON(), allocator); + + JsonRequest::create(doc, m_sequence++, "getblocktemplate", params); + + send(HTTP_POST, "/json_rpc", doc); +} + + +void xmrig::SelfSelectClient::retry() +{ + setState(RetryState); +} + + +void xmrig::SelfSelectClient::send(int method, const char *url, const char *data, size_t size) +{ + LOG_DEBUG("[%s] " MAGENTA_BOLD("\"%s %s\"") BLACK_BOLD_S " send (%zu bytes): \"%.*s\"", + pool().daemon().url().data(), + http_method_str(static_cast(method)), + url, + size, + static_cast(size), + data); + + HttpClient *client; +# ifdef XMRIG_FEATURE_TLS + if (pool().daemon().isTLS()) { + client = new HttpsClient(method, url, this, data, size, String()); + } + else +# endif + { + client = new HttpClient(method, url, this, data, size); + } + + client->setQuiet(isQuiet()); + client->connect(pool().daemon().host(), pool().daemon().port()); +} + + +void xmrig::SelfSelectClient::send(int method, const char *url, const rapidjson::Document &doc) +{ + using namespace rapidjson; + + StringBuffer buffer(nullptr, 512); + Writer writer(buffer); + doc.Accept(writer); + + send(method, url, buffer.GetString(), buffer.GetSize()); +} + + +void xmrig::SelfSelectClient::setState(State state) +{ + if (m_state == state) { + return; + } + + switch (state) { + case IdleState: + m_timestamp = 0; + m_failures = 0; + break; + + case WaitState: + m_timestamp = Chrono::steadyMSecs(); + break; + + case RetryState: + m_timestamp = Chrono::steadyMSecs(); + + if (m_failures > m_retries) { + m_listener->onClose(this, static_cast(m_failures)); + } + + m_failures++; + break; + } + + m_state = state; +} + + +void xmrig::SelfSelectClient::submitBlockTemplate(rapidjson::Value &result) +{ + using namespace rapidjson; + Document doc(kObjectType); + auto &allocator = doc.GetAllocator(); + + Value params(kObjectType); + params.AddMember(StringRef(kId), m_job.clientId().toJSON(), allocator); + params.AddMember(StringRef(kJobId), m_job.id().toJSON(), allocator); + params.AddMember(StringRef(kBlob), result[kBlocktemplateBlob], allocator); + params.AddMember(StringRef(kHeight), m_job.height(), allocator); + params.AddMember(StringRef(kDifficulty), result[kDifficulty], allocator); + params.AddMember(StringRef(kPrevHash), result[kPrevHash], allocator); + params.AddMember(StringRef(kSeedHash), result[kSeedHash], allocator); + params.AddMember(StringRef(kNextSeedHash), result[kNextSeedHash], allocator); + + JsonRequest::create(doc, sequence(), "block_template", params); + + send(doc, [this](const rapidjson::Value &result, bool success, uint64_t elapsed) { + if (!success) { + if (!isQuiet()) { + LOG_ERR("[%s] error: " RED_BOLD("\"%s\"") RED_S ", code: %d", pool().daemon().url().data(), Json::getString(result, "message"), Json::getInt(result, "code")); + } + + return retry(); + } + + if (!m_active) { + return; + } + + if (m_failures > m_retries) { + m_listener->onLoginSuccess(this); + } + + setState(IdleState); + m_listener->onJobReceived(this, m_job, rapidjson::Value{}); + }); +} + + +void xmrig::SelfSelectClient::onHttpData(const HttpData &data) +{ + if (data.status != HTTP_STATUS_OK) { + return retry(); + } + + LOG_DEBUG("[%s] received (%d bytes): \"%.*s\"", pool().daemon().url().data(), static_cast(data.body.size()), static_cast(data.body.size()), data.body.c_str()); + + rapidjson::Document doc; + if (doc.Parse(data.body.c_str()).HasParseError()) { + if (!isQuiet()) { + LOG_ERR("[%s] JSON decode failed: \"%s\"", pool().daemon().url().data(), rapidjson::GetParseError_En(doc.GetParseError())); + } + + return retry(); + } + + const int64_t id = Json::getInt64(doc, "id", -1); + if (id > 0 && m_sequence - id != 1) { + return; + } + + if (!parseResponse(id, doc["result"], Json::getObject(doc, "error"))) { + retry(); + } +} diff --git a/src/base/net/stratum/SelfSelectClient.h b/src/base/net/stratum/SelfSelectClient.h new file mode 100644 index 000000000..c48c50782 --- /dev/null +++ b/src/base/net/stratum/SelfSelectClient.h @@ -0,0 +1,123 @@ +/* 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-2019 SChernykh + * Copyright 2019 jtgrassie + * Copyright 2016-2019 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 XMRIG_SELFSELECTCLIENT_H +#define XMRIG_SELFSELECTCLIENT_H + + +#include "base/kernel/interfaces/IClient.h" +#include "base/kernel/interfaces/IClientListener.h" +#include "base/kernel/interfaces/IHttpListener.h" +#include "base/net/stratum/Job.h" +#include "base/tools/Object.h" + + +namespace xmrig { + + +class SelfSelectClient : public IClient, public IClientListener, public IHttpListener +{ +public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(SelfSelectClient) + + SelfSelectClient(int id, const char *agent, IClientListener *listener); + ~SelfSelectClient() override; + +protected: + // IClient + inline bool disconnect() override { return m_client->disconnect(); } + inline bool hasExtension(Extension extension) const noexcept override { return m_client->hasExtension(extension); } + inline bool isEnabled() const override { return m_client->isEnabled(); } + inline bool isTLS() const override { return m_client->isTLS(); } + inline const char *mode() const override { return m_client->mode(); } + inline const char *tlsFingerprint() const override { return m_client->tlsFingerprint(); } + inline const char *tlsVersion() const override { return m_client->tlsVersion(); } + inline const Job &job() const override { return m_client->job(); } + inline const Pool &pool() const override { return m_client->pool(); } + inline const String &ip() const override { return m_client->ip(); } + inline int id() const override { return m_client->id(); } + inline int64_t send(const rapidjson::Value &obj, Callback callback) override { return m_client->send(obj, callback); } + inline int64_t send(const rapidjson::Value &obj) override { return m_client->send(obj); } + inline int64_t sequence() const override { return m_client->sequence(); } + inline int64_t submit(const JobResult &result) override { return m_client->submit(result); } + inline void connect() override { m_client->connect(); } + inline void connect(const Pool &pool) override { m_client->connect(pool); } + inline void deleteLater() override { m_client->deleteLater(); } + inline void setAlgo(const Algorithm &algo) override { m_client->setAlgo(algo); } + inline void setEnabled(bool enabled) override { m_client->setEnabled(enabled); } + inline void setPool(const Pool &pool) override { m_client->setPool(pool); } + inline void setQuiet(bool quiet) override { m_client->setQuiet(quiet); m_quiet = quiet; } + inline void setRetries(int retries) override { m_client->setRetries(retries); m_retries = retries; } + inline void setRetryPause(uint64_t ms) override { m_client->setRetryPause(ms); m_retryPause = ms; } + + void tick(uint64_t now) override; + + // IClientListener + inline void onClose(IClient *, int failures) override { m_listener->onClose(this, failures); setState(IdleState); m_active = false; } + inline void onLoginSuccess(IClient *) override { m_listener->onLoginSuccess(this); setState(IdleState); m_active = true; } + inline void onResultAccepted(IClient *, const SubmitResult &result, const char *error) override { m_listener->onResultAccepted(this, result, error); } + inline void onVerifyAlgorithm(const IClient *, const Algorithm &algorithm, bool *ok) override { m_listener->onVerifyAlgorithm(this, algorithm, ok); } + + void onJobReceived(IClient *, const Job &job, const rapidjson::Value ¶ms) override; + void onLogin(IClient *, rapidjson::Document &doc, rapidjson::Value ¶ms) override; + + // IHttpListener + void onHttpData(const HttpData &data) override; + +private: + enum State { + IdleState, + WaitState, + RetryState + }; + + inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; } + + bool parseResponse(int64_t id, rapidjson::Value &result, const rapidjson::Value &error); + void getBlockTemplate(); + void retry(); + void send(int method, const char *url, const char *data = nullptr, size_t size = 0); + void send(int method, const char *url, const rapidjson::Document &doc); + void setState(State state); + void submitBlockTemplate(rapidjson::Value &result); + + bool m_active = false; + bool m_quiet = false; + IClient *m_client; + IClientListener *m_listener; + int m_retries = 5; + int64_t m_failures = 0; + int64_t m_sequence = 1; + Job m_job; + State m_state = IdleState; + uint64_t m_retryPause = 5000; + uint64_t m_timestamp = 0; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_SELFSELECTCLIENT_H */ diff --git a/src/base/net/stratum/SubmitResult.h b/src/base/net/stratum/SubmitResult.h index 5abd3e4bf..1b49acb43 100644 --- a/src/base/net/stratum/SubmitResult.h +++ b/src/base/net/stratum/SubmitResult.h @@ -35,34 +35,26 @@ namespace xmrig { class SubmitResult { public: - inline SubmitResult() : - reqId(0), - seq(0), - actualDiff(0), - diff(0), - elapsed(0), - m_start(0) - {} + SubmitResult() = default; inline SubmitResult(int64_t seq, uint64_t diff, uint64_t actualDiff, int64_t reqId = 0) : reqId(reqId), seq(seq), actualDiff(actualDiff), diff(diff), - elapsed(0), m_start(Chrono::steadyMSecs()) {} inline void done() { elapsed = Chrono::steadyMSecs() - m_start; } - int64_t reqId; - int64_t seq; - uint64_t actualDiff; - uint64_t diff; - uint64_t elapsed; + int64_t reqId = 0; + int64_t seq = 0; + uint64_t actualDiff = 0; + uint64_t diff = 0; + uint64_t elapsed = 0; private: - uint64_t m_start; + uint64_t m_start = 0; }; diff --git a/src/base/net/stratum/Url.cpp b/src/base/net/stratum/Url.cpp new file mode 100644 index 000000000..3de6bc9b8 --- /dev/null +++ b/src/base/net/stratum/Url.cpp @@ -0,0 +1,163 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2019 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu + * Copyright 2016-2019 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 "base/net/stratum/Url.h" + + +#include +#include +#include +#include + + +#ifdef _MSC_VER +# define strncasecmp _strnicmp +#endif + + +namespace xmrig { + +static const char kStratumTcp[] = "stratum+tcp://"; +static const char kStratumSsl[] = "stratum+ssl://"; + +#ifdef XMRIG_FEATURE_HTTP +static const char kDaemonHttp[] = "daemon+http://"; +static const char kDaemonHttps[] = "daemon+https://"; +#endif + +} + + +xmrig::Url::Url(const char *url) +{ + parse(url); +} + + +xmrig::Url::Url(const char *host, uint16_t port, bool tls, Scheme scheme) : + m_tls(tls), + m_scheme(scheme), + m_host(host), + m_port(port) +{ + const size_t size = m_host.size() + 8; + assert(size > 8); + + char *url = new char[size](); + snprintf(url, size - 1, "%s:%d", m_host.data(), m_port); + + m_url = url; +} + + +bool xmrig::Url::isEqual(const Url &other) const +{ + return (m_tls == other.m_tls && m_scheme == other.m_scheme && m_host == other.m_host && m_url == other.m_url && m_port == other.m_port); +} + + +bool xmrig::Url::parse(const char *url) +{ + if (url == nullptr) { + return false; + } + + const char *p = strstr(url, "://"); + const char *base = url; + + if (p) { + if (strncasecmp(url, kStratumTcp, sizeof(kStratumTcp) - 1) == 0) { + m_scheme = STRATUM; + m_tls = false; + } + else if (strncasecmp(url, kStratumSsl, sizeof(kStratumSsl) - 1) == 0) { + m_scheme = STRATUM; + m_tls = true; + } +# ifdef XMRIG_FEATURE_HTTP + else if (strncasecmp(url, kDaemonHttps, sizeof(kDaemonHttps) - 1) == 0) { + m_scheme = DAEMON; + m_tls = true; + } + else if (strncasecmp(url, kDaemonHttp, sizeof(kDaemonHttp) - 1) == 0) { + m_scheme = DAEMON; + m_tls = false; + } +# endif + else { + return false; + } + + base = p + 3; + } + + if (!strlen(base) || *base == '/') { + return false; + } + + m_url = url; + if (base[0] == '[') { + return parseIPv6(base); + } + + const char *port = strchr(base, ':'); + if (!port) { + m_host = base; + return true; + } + + const auto size = static_cast(port++ - base + 1); + char *host = new char[size](); + memcpy(host, base, size - 1); + + m_host = host; + m_port = static_cast(strtol(port, nullptr, 10)); + + return true; +} + + +bool xmrig::Url::parseIPv6(const char *addr) +{ + const char *end = strchr(addr, ']'); + if (!end) { + return false; + } + + const char *port = strchr(end, ':'); + if (!port) { + return false; + } + + const auto size = static_cast(end - addr); + char *host = new char[size](); + memcpy(host, addr + 1, size - 1); + + m_host = host; + m_port = static_cast(strtol(port + 1, nullptr, 10)); + + return true; +} diff --git a/src/base/net/stratum/Url.h b/src/base/net/stratum/Url.h new file mode 100644 index 000000000..23fd750e9 --- /dev/null +++ b/src/base/net/stratum/Url.h @@ -0,0 +1,77 @@ +/* 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-2019 SChernykh + * Copyright 2019 Howard Chu + * Copyright 2016-2019 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 XMRIG_URL_H +#define XMRIG_URL_H + + +#include "base/tools/String.h" + + +namespace xmrig { + + +class Url +{ +public: + enum Scheme { + UNSPECIFIED, + STRATUM, + DAEMON + }; + + Url() = default; + Url(const char *url); + Url(const char *host, uint16_t port, bool tls = false, Scheme scheme = UNSPECIFIED); + + inline bool isTLS() const { return m_tls; } + inline bool isValid() const { return !m_host.isNull() && m_port > 0; } + inline const String &host() const { return m_host; } + inline const String &url() const { return m_url; } + inline Scheme scheme() const { return m_scheme; } + inline uint16_t port() const { return m_port; } + + inline bool operator!=(const Url &other) const { return !isEqual(other); } + inline bool operator==(const Url &other) const { return isEqual(other); } + + bool isEqual(const Url &other) const; + rapidjson::Value toJSON(rapidjson::Document &doc) const; + +private: + bool parse(const char *url); + bool parseIPv6(const char *addr); + + bool m_tls = false; + Scheme m_scheme = UNSPECIFIED; + String m_host; + String m_url; + uint16_t m_port = 3333; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_URL_H */ diff --git a/src/base/net/stratum/strategies/FailoverStrategy.cpp b/src/base/net/stratum/strategies/FailoverStrategy.cpp index 48be2ba35..28c1ad99f 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.cpp +++ b/src/base/net/stratum/strategies/FailoverStrategy.cpp @@ -23,15 +23,10 @@ */ +#include "base/net/stratum/strategies/FailoverStrategy.h" +#include "base/kernel/interfaces/IClient.h" #include "base/kernel/interfaces/IStrategyListener.h" #include "base/kernel/Platform.h" -#include "base/net/stratum/Client.h" -#include "base/net/stratum/strategies/FailoverStrategy.h" - - -#ifdef XMRIG_FEATURE_HTTP -# include "base/net/stratum/DaemonClient.h" -#endif xmrig::FailoverStrategy::FailoverStrategy(const std::vector &pools, int retryPause, int retries, IStrategyListener *listener, bool quiet) : @@ -69,16 +64,8 @@ xmrig::FailoverStrategy::~FailoverStrategy() void xmrig::FailoverStrategy::add(const Pool &pool) { - const int id = static_cast(m_pools.size()); - -# ifdef XMRIG_FEATURE_HTTP - IClient *client = !pool.isDaemon() ? static_cast(new Client(id, Platform::userAgent(), this)) - : static_cast(new DaemonClient(id, this)); -# else - IClient *client = new Client(id, Platform::userAgent(), this); -# endif + IClient *client = pool.createClient(static_cast(m_pools.size()), this); - client->setPool(pool); client->setRetries(m_retries); client->setRetryPause(m_retryPause * 1000); client->setQuiet(m_quiet); @@ -123,8 +110,8 @@ void xmrig::FailoverStrategy::setAlgo(const Algorithm &algo) void xmrig::FailoverStrategy::stop() { - for (size_t i = 0; i < m_pools.size(); ++i) { - m_pools[i]->disconnect(); + for (auto &pool : m_pools) { + pool->disconnect(); } m_index = 0; diff --git a/src/base/net/stratum/strategies/FailoverStrategy.h b/src/base/net/stratum/strategies/FailoverStrategy.h index 283d49165..c69160ee9 100644 --- a/src/base/net/stratum/strategies/FailoverStrategy.h +++ b/src/base/net/stratum/strategies/FailoverStrategy.h @@ -32,6 +32,7 @@ #include "base/kernel/interfaces/IClientListener.h" #include "base/kernel/interfaces/IStrategy.h" #include "base/net/stratum/Pool.h" +#include "base/tools/Object.h" namespace xmrig { @@ -44,6 +45,8 @@ class IStrategyListener; class FailoverStrategy : public IStrategy, public IClientListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(FailoverStrategy) + FailoverStrategy(const std::vector &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet = false); FailoverStrategy(int retryPause, int retries, IStrategyListener *listener, bool quiet = false); ~FailoverStrategy() override; diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.cpp b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp index c923e1c2c..a45be658f 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.cpp +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.cpp @@ -23,33 +23,18 @@ */ +#include "base/net/stratum/strategies/SinglePoolStrategy.h" +#include "base/kernel/interfaces/IClient.h" #include "base/kernel/interfaces/IStrategyListener.h" #include "base/kernel/Platform.h" -#include "base/net/stratum/Client.h" -#include "base/net/stratum/strategies/SinglePoolStrategy.h" - - -#ifdef XMRIG_FEATURE_HTTP -# include "base/net/stratum/DaemonClient.h" -#endif +#include "base/net/stratum/Pool.h" xmrig::SinglePoolStrategy::SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet) : m_active(false), m_listener(listener) { -# ifdef XMRIG_FEATURE_HTTP - if (!pool.isDaemon()) { - m_client = new Client(0, Platform::userAgent(), this); - } - else { - m_client = new DaemonClient(0, this); - } -# else - m_client = new Client(0, Platform::userAgent(), this); -# endif - - m_client->setPool(pool); + m_client = pool.createClient(0, this); m_client->setRetries(retries); m_client->setRetryPause(retryPause * 1000); m_client->setQuiet(quiet); diff --git a/src/base/net/stratum/strategies/SinglePoolStrategy.h b/src/base/net/stratum/strategies/SinglePoolStrategy.h index ea808193c..f2c8b2297 100644 --- a/src/base/net/stratum/strategies/SinglePoolStrategy.h +++ b/src/base/net/stratum/strategies/SinglePoolStrategy.h @@ -28,6 +28,7 @@ #include "base/kernel/interfaces/IClientListener.h" #include "base/kernel/interfaces/IStrategy.h" +#include "base/tools/Object.h" namespace xmrig { @@ -41,6 +42,8 @@ class Pool; class SinglePoolStrategy : public IStrategy, public IClientListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(SinglePoolStrategy) + SinglePoolStrategy(const Pool &pool, int retryPause, int retries, IStrategyListener *listener, bool quiet = false); ~SinglePoolStrategy() override; diff --git a/src/base/tools/Buffer.cpp b/src/base/tools/Buffer.cpp index 05a68cb4c..c12e601db 100644 --- a/src/base/tools/Buffer.cpp +++ b/src/base/tools/Buffer.cpp @@ -53,14 +53,7 @@ static inline uint8_t hf_bin2hex(uint8_t c) } -xmrig::Buffer::Buffer() : - m_data(nullptr), - m_size(0) -{ -} - - -xmrig::Buffer::Buffer(Buffer &&other) : +xmrig::Buffer::Buffer(Buffer &&other) noexcept : m_data(other.m_data), m_size(other.m_size) { @@ -138,11 +131,13 @@ bool xmrig::Buffer::fromHex(const uint8_t *in, size_t size, uint8_t *out) xmrig::Buffer xmrig::Buffer::fromHex(const char *data, size_t size) { if (data == nullptr || size % 2 != 0) { - return Buffer(); + return {}; } Buffer buf(size / 2); - fromHex(data, size, buf.data()); + if (!fromHex(data, size, buf.data())) { + return {}; + } return buf; } @@ -157,12 +152,6 @@ void xmrig::Buffer::toHex(const uint8_t *in, size_t size, uint8_t *out) } -xmrig::String xmrig::Buffer::toHex(const uint8_t *in, size_t size) -{ - return Buffer(reinterpret_cast(in), size).toHex(); -} - - xmrig::String xmrig::Buffer::toHex() const { if (m_size == 0) { diff --git a/src/base/tools/Buffer.h b/src/base/tools/Buffer.h index 28f92b9e1..363e4697e 100644 --- a/src/base/tools/Buffer.h +++ b/src/base/tools/Buffer.h @@ -35,14 +35,15 @@ namespace xmrig { class Buffer { public: - Buffer(); - Buffer(Buffer &&other); + Buffer() = default; + Buffer(Buffer &&other) noexcept; Buffer(const Buffer &other); Buffer(const char *data, size_t size); Buffer(size_t size); ~Buffer(); + inline bool isEmpty() const { return size() == 0; } inline bool isEqual(const Buffer &other) const { return m_size == other.m_size && (m_size == 0 || memcmp(m_data, other.m_data, m_size) == 0); } inline char *data() { return m_data; } inline const char *data() const { return m_data; } @@ -55,7 +56,7 @@ class Buffer inline bool operator!=(const Buffer &other) const { return !isEqual(other); } inline bool operator==(const Buffer &other) const { return isEqual(other); } - inline Buffer &operator=(Buffer &&other) { move(std::move(other)); return *this; } + inline Buffer &operator=(Buffer &&other) noexcept { move(std::move(other)); return *this; } inline Buffer &operator=(const Buffer &other) { from(other); return *this; } @@ -67,12 +68,13 @@ class Buffer inline static bool fromHex(const char *in, size_t size, uint8_t *out) { return fromHex(reinterpret_cast(in), size, out); } inline static Buffer fromHex(const char *data) { return fromHex(data, strlen(data)); } inline static Buffer fromHex(const String &str) { return fromHex(str.data(), str.size()); } + inline static String toHex(const char *in, size_t size) { return Buffer(in, size).toHex(); } + inline static String toHex(const uint8_t *in, size_t size) { return Buffer(reinterpret_cast(in), size).toHex(); } inline static void toHex(const char *in, size_t size, char *out) { return toHex(reinterpret_cast(in), size, reinterpret_cast(out)); } inline static void toHex(const uint8_t *in, size_t size, char *out) { return toHex(in, size, reinterpret_cast(out)); } static bool fromHex(const uint8_t *in, size_t size, uint8_t *out); static Buffer fromHex(const char *data, size_t size); - static String toHex(const uint8_t *in, size_t size); static void toHex(const uint8_t *in, size_t size, uint8_t *out); String toHex() const; @@ -80,8 +82,8 @@ class Buffer void copy(const char *data, size_t size); void move(Buffer &&other); - char *m_data; - size_t m_size; + char *m_data = nullptr; + size_t m_size = 0; }; diff --git a/src/base/tools/String.cpp b/src/base/tools/String.cpp index 7778c6da6..b11d67745 100644 --- a/src/base/tools/String.cpp +++ b/src/base/tools/String.cpp @@ -31,7 +31,6 @@ xmrig::String::String(const char *str) : - m_data(nullptr), m_size(str == nullptr ? 0 : strlen(str)) { if (m_size == 0) { @@ -44,7 +43,6 @@ xmrig::String::String(const char *str) : xmrig::String::String(const char *str, size_t size) : - m_data(nullptr), m_size(size) { if (str == nullptr) { @@ -60,7 +58,6 @@ xmrig::String::String(const char *str, size_t size) : xmrig::String::String(const String &other) : - m_data(nullptr), m_size(other.m_size) { if (other.m_data == nullptr) { @@ -117,7 +114,7 @@ std::vector xmrig::String::split(char sep) const for (pos = 0; pos < m_size; ++pos) { if (m_data[pos] == sep) { if ((pos - start) > 0) { - out.push_back(String(m_data + start, pos - start)); + out.emplace_back(m_data + start, pos - start); } start = pos + 1; @@ -125,7 +122,7 @@ std::vector xmrig::String::split(char sep) const } if ((pos - start) > 0) { - out.push_back(String(m_data + start, pos - start)); + out.emplace_back(m_data + start, pos - start); } return out; @@ -146,6 +143,20 @@ xmrig::String &xmrig::String::toLower() } +xmrig::String &xmrig::String::toUpper() +{ + if (isNull() || isEmpty()) { + return *this; + } + + for (size_t i = 0; i < size(); ++i) { + m_data[i] = static_cast(toupper(m_data[i])); + } + + return *this; +} + + xmrig::String xmrig::String::join(const std::vector &vec, char sep) { if (vec.empty()) { diff --git a/src/base/tools/String.h b/src/base/tools/String.h index 2c47d8501..0f3656410 100644 --- a/src/base/tools/String.h +++ b/src/base/tools/String.h @@ -46,9 +46,9 @@ namespace xmrig { class String { public: - inline String() : m_data(nullptr), m_size(0) {} - inline String(char *str) : m_data(str), m_size(str == nullptr ? 0 : strlen(str)) {} - inline String(String &&other) : m_data(other.m_data), m_size(other.m_size) { other.m_data = nullptr; other.m_size = 0; } + inline String() = default; + inline String(char *str) : m_data(str), m_size(str == nullptr ? 0 : strlen(str)) {} + inline String(String &&other) noexcept : m_data(other.m_data), m_size(other.m_size) { other.m_data = nullptr; other.m_size = 0; } String(const char *str); String(const char *str, size_t size); @@ -81,12 +81,13 @@ class String inline String &operator=(const char *str) { copy(str); return *this; } inline String &operator=(const String &str) { copy(str); return *this; } inline String &operator=(std::nullptr_t) { delete [] m_data; m_data = nullptr; m_size = 0; return *this; } - inline String &operator=(String &&other) { move(std::move(other)); return *this; } + inline String &operator=(String &&other) noexcept { move(std::move(other)); return *this; } rapidjson::Value toJSON() const; rapidjson::Value toJSON(rapidjson::Document &doc) const; std::vector split(char sep) const; String &toLower(); + String &toUpper(); static String join(const std::vector &vec, char sep); @@ -96,8 +97,8 @@ class String void move(char *str); void move(String &&other); - char *m_data; - size_t m_size; + char *m_data = nullptr; + size_t m_size = 0; }; diff --git a/src/core/config/usage.h b/src/core/config/usage.h index bc52e9f73..a7e89937e 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -29,10 +29,13 @@ #include "version.h" +#include + + namespace xmrig { -static char const usage[] = "\ +static char const usage_raw[] = "\ Usage: " APP_ID " [OPTIONS]\n\ Options:\n\ -b, --bind=ADDR bind to specified address, example \"0.0.0.0:3333\"\n\ @@ -90,6 +93,18 @@ Options:\n\ "; +static inline const std::string &usage() +{ + static std::string u; + + if (u.empty()) { + u = usage_raw; + } + + return u; +} + + } /* namespace xmrig */ #endif /* XMRIG_USAGE_H */ From 36704047e1bb5aff7e05f8db5d33f63796dfa819 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 23 Oct 2019 03:03:24 +0700 Subject: [PATCH 2/7] v4.4.0-evo --- src/version.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/version.h b/src/version.h index 97fd4e2b7..c9d6ecebf 100644 --- a/src/version.h +++ b/src/version.h @@ -28,15 +28,15 @@ #define APP_ID "xmrig-proxy" #define APP_NAME "xmrig-proxy" #define APP_DESC "XMRig Stratum proxy" -#define APP_VERSION "3.2.1-dev" +#define APP_VERSION "4.4.0-evo" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" #define APP_KIND "proxy" -#define APP_VER_MAJOR 3 -#define APP_VER_MINOR 2 -#define APP_VER_PATCH 1 +#define APP_VER_MAJOR 4 +#define APP_VER_MINOR 4 +#define APP_VER_PATCH 0 #ifdef _MSC_VER # if (_MSC_VER >= 1920) From 6ace89f832bf7e2ab46bed6e8a33a2eaf2eb43b1 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 28 Oct 2019 16:52:13 +0700 Subject: [PATCH 3/7] #348 Added missing rx/arq. --- src/crypto/cn/CnAlgo.h | 249 +++++++++++++++++--------------- src/crypto/common/Algorithm.cpp | 45 +++--- src/crypto/common/Algorithm.h | 27 ++-- src/crypto/common/Coin.cpp | 11 +- src/crypto/common/Coin.h | 1 + 5 files changed, 177 insertions(+), 156 deletions(-) diff --git a/src/crypto/cn/CnAlgo.h b/src/crypto/cn/CnAlgo.h index ed64331a9..b6a76089e 100644 --- a/src/crypto/cn/CnAlgo.h +++ b/src/crypto/cn/CnAlgo.h @@ -27,8 +27,8 @@ #define XMRIG_CN_ALGO_H -#include -#include +#include +#include #include "crypto/common/Algorithm.h" @@ -42,20 +42,14 @@ template class CnAlgo { public: - constexpr inline CnAlgo() - { - static_assert(ALGO != Algorithm::INVALID && m_memory[ALGO] > 0, "invalid CRYPTONIGHT algorithm"); - static_assert(sizeof(m_memory) / sizeof(m_memory)[0] == Algorithm::MAX, "memory table size mismatch"); - static_assert(sizeof(m_iterations) / sizeof(m_iterations)[0] == Algorithm::MAX, "iterations table size mismatch"); - static_assert(sizeof(m_base) / sizeof(m_base)[0] == Algorithm::MAX, "iterations table size mismatch"); - } + constexpr CnAlgo() {}; - constexpr inline Algorithm::Id base() const { return m_base[ALGO]; } + constexpr inline Algorithm::Id base() const { static_assert(ALGO > Algorithm::INVALID && ALGO < Algorithm::RX_0, "invalid CRYPTONIGHT algorithm"); return Algorithm::CN_2; } constexpr inline bool isHeavy() const { return memory() == CN_MEMORY * 2; } - constexpr inline bool isR() const { return ALGO == Algorithm::CN_R || ALGO == Algorithm::CN_WOW; } - constexpr inline size_t memory() const { return m_memory[ALGO]; } - constexpr inline uint32_t iterations() const { return m_iterations[ALGO]; } - constexpr inline uint32_t mask() const { return ((memory() - 1) / 16) * 16; } + constexpr inline bool isR() const { return ALGO == Algorithm::CN_R; } + constexpr inline size_t memory() const { static_assert(ALGO > Algorithm::INVALID && ALGO < Algorithm::RX_0, "invalid CRYPTONIGHT algorithm"); return CN_MEMORY; } + constexpr inline uint32_t iterations() const { static_assert(ALGO > Algorithm::INVALID && ALGO < Algorithm::RX_0, "invalid CRYPTONIGHT algorithm"); return CN_ITER; } + constexpr inline uint32_t mask() const { return static_cast(((memory() - 1) / 16) * 16); } inline static size_t memory(Algorithm::Id algo) { @@ -79,6 +73,54 @@ class CnAlgo return 0; } + inline static uint32_t iterations(Algorithm::Id algo) + { + switch (algo) { + case Algorithm::CN_0: + case Algorithm::CN_1: + case Algorithm::CN_2: + case Algorithm::CN_R: + case Algorithm::CN_RTO: + return CN_ITER; + + case Algorithm::CN_FAST: + case Algorithm::CN_HALF: +# ifdef XMRIG_ALGO_CN_LITE + case Algorithm::CN_LITE_0: + case Algorithm::CN_LITE_1: +# endif +# ifdef XMRIG_ALGO_CN_HEAVY + case Algorithm::CN_HEAVY_0: + case Algorithm::CN_HEAVY_TUBE: + case Algorithm::CN_HEAVY_XHV: +# endif + return CN_ITER / 2; + + case Algorithm::CN_RWZ: + case Algorithm::CN_ZLS: + return 0x60000; + + case Algorithm::CN_XAO: + case Algorithm::CN_DOUBLE: + return CN_ITER * 2; + +# ifdef XMRIG_ALGO_CN_GPU + case Algorithm::CN_GPU: + return 0xC000; +# endif + +# ifdef XMRIG_ALGO_CN_PICO + case Algorithm::CN_PICO_0: + return CN_ITER / 8; +# endif + + default: + break; + } + + return 0; + } + inline static uint32_t mask(Algorithm::Id algo) { # ifdef XMRIG_ALGO_CN_GPU @@ -96,124 +138,97 @@ class CnAlgo return ((memory(algo) - 1) / 16) * 16; } -private: - constexpr const static size_t CN_MEMORY = 0x200000; - constexpr const static uint32_t CN_ITER = 0x80000; - - constexpr const static size_t m_memory[] = { - CN_MEMORY, // CN_0 - CN_MEMORY, // CN_1 - CN_MEMORY, // CN_2 - CN_MEMORY, // CN_R - CN_MEMORY, // CN_WOW - CN_MEMORY, // CN_FAST - CN_MEMORY, // CN_HALF - CN_MEMORY, // CN_XAO - CN_MEMORY, // CN_RTO - CN_MEMORY, // CN_RWZ - CN_MEMORY, // CN_ZLS - CN_MEMORY, // CN_DOUBLE -# ifdef XMRIG_ALGO_CN_GPU - CN_MEMORY, // CN_GPU -# endif + inline static Algorithm::Id base(Algorithm::Id algo) + { + switch (algo) { + case Algorithm::CN_0: + case Algorithm::CN_XAO: # ifdef XMRIG_ALGO_CN_LITE - CN_MEMORY / 2, // CN_LITE_0 - CN_MEMORY / 2, // CN_LITE_1 + case Algorithm::CN_LITE_0: # endif # ifdef XMRIG_ALGO_CN_HEAVY - CN_MEMORY * 2, // CN_HEAVY_0 - CN_MEMORY * 2, // CN_HEAVY_TUBE - CN_MEMORY * 2, // CN_HEAVY_XHV -# endif -# ifdef XMRIG_ALGO_CN_PICO - CN_MEMORY / 8, // CN_PICO_0 -# endif -# ifdef XMRIG_ALGO_RANDOMX - 0, // RX_0 - 0, // RX_WOW - 0, // RX_LOKI -# endif - }; - - constexpr const static uint32_t m_iterations[] = { - CN_ITER, // CN_0 - CN_ITER, // CN_1 - CN_ITER, // CN_2 - CN_ITER, // CN_R - CN_ITER, // CN_WOW - CN_ITER / 2, // CN_FAST - CN_ITER / 2, // CN_HALF - CN_ITER * 2, // CN_XAO - CN_ITER, // CN_RTO - 0x60000, // CN_RWZ - 0x60000, // CN_ZLS - CN_ITER * 2, // CN_DOUBLE -# ifdef XMRIG_ALGO_CN_GPU - 0xC000, // CN_GPU + case Algorithm::CN_HEAVY_0: + case Algorithm::CN_HEAVY_XHV: # endif + return Algorithm::CN_0; + + case Algorithm::CN_1: + case Algorithm::CN_FAST: + case Algorithm::CN_RTO: # ifdef XMRIG_ALGO_CN_LITE - CN_ITER / 2, // CN_LITE_0 - CN_ITER / 2, // CN_LITE_1 + case Algorithm::CN_LITE_1: # endif # ifdef XMRIG_ALGO_CN_HEAVY - CN_ITER / 2, // CN_HEAVY_0 - CN_ITER / 2, // CN_HEAVY_TUBE - CN_ITER / 2, // CN_HEAVY_XHV + case Algorithm::CN_HEAVY_TUBE: + return Algorithm::CN_1; # endif + + case Algorithm::CN_2: + case Algorithm::CN_R: + case Algorithm::CN_HALF: + case Algorithm::CN_RWZ: + case Algorithm::CN_ZLS: + case Algorithm::CN_DOUBLE: # ifdef XMRIG_ALGO_CN_PICO - CN_ITER / 8, // CN_PICO_0 -# endif -# ifdef XMRIG_ALGO_RANDOMX - 0, // RX_0 - 0, // RX_WOW - 0, // RX_LOKI + case Algorithm::CN_PICO_0: # endif - }; - - constexpr const static Algorithm::Id m_base[] = { - Algorithm::CN_0, // CN_0 - Algorithm::CN_1, // CN_1 - Algorithm::CN_2, // CN_2 - Algorithm::CN_2, // CN_R - Algorithm::CN_2, // CN_WOW - Algorithm::CN_1, // CN_FAST - Algorithm::CN_2, // CN_HALF - Algorithm::CN_0, // CN_XAO - Algorithm::CN_1, // CN_RTO - Algorithm::CN_2, // CN_RWZ - Algorithm::CN_2, // CN_ZLS - Algorithm::CN_2, // CN_DOUBLE + return Algorithm::CN_2; + # ifdef XMRIG_ALGO_CN_GPU - Algorithm::CN_GPU, // CN_GPU -# endif -# ifdef XMRIG_ALGO_CN_LITE - Algorithm::CN_0, // CN_LITE_0 - Algorithm::CN_1, // CN_LITE_1 -# endif -# ifdef XMRIG_ALGO_CN_HEAVY - Algorithm::CN_0, // CN_HEAVY_0 - Algorithm::CN_1, // CN_HEAVY_TUBE - Algorithm::CN_0, // CN_HEAVY_XHV + case Algorithm::CN_GPU: + return Algorithm::CN_GPU; # endif -# ifdef XMRIG_ALGO_CN_PICO - Algorithm::CN_2, // CN_PICO_0, -# endif -# ifdef XMRIG_ALGO_RANDOMX - Algorithm::INVALID, // RX_0 - Algorithm::INVALID, // RX_WOW - Algorithm::INVALID, // RX_LOKI -# endif - }; -}; + default: + break; + } + + return Algorithm::INVALID; + } + +private: + constexpr const static size_t CN_MEMORY = 0x200000; + constexpr const static uint32_t CN_ITER = 0x80000; +}; -#ifdef XMRIG_ALGO_CN_GPU -template<> constexpr inline uint32_t CnAlgo::mask() const { return 0x1FFFC0; } -#endif -#ifdef XMRIG_ALGO_CN_PICO -template<> constexpr inline uint32_t CnAlgo::mask() const { return 0x1FFF0; } -#endif +template<> constexpr inline Algorithm::Id CnAlgo::base() const { return Algorithm::CN_0; } +template<> constexpr inline Algorithm::Id CnAlgo::base() const { return Algorithm::CN_0; } +template<> constexpr inline Algorithm::Id CnAlgo::base() const { return Algorithm::CN_0; } +template<> constexpr inline Algorithm::Id CnAlgo::base() const { return Algorithm::CN_0; } +template<> constexpr inline Algorithm::Id CnAlgo::base() const { return Algorithm::CN_0; } +template<> constexpr inline Algorithm::Id CnAlgo::base() const { return Algorithm::CN_1; } +template<> constexpr inline Algorithm::Id CnAlgo::base() const { return Algorithm::CN_1; } +template<> constexpr inline Algorithm::Id CnAlgo::base() const { return Algorithm::CN_1; } +template<> constexpr inline Algorithm::Id CnAlgo::base() const { return Algorithm::CN_1; } +template<> constexpr inline Algorithm::Id CnAlgo::base() const { return Algorithm::CN_1; } + + +template<> constexpr inline uint32_t CnAlgo::iterations() const { return CN_ITER / 2; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return CN_ITER / 2; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return CN_ITER / 2; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return CN_ITER / 2; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return CN_ITER / 2; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return CN_ITER / 2; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return CN_ITER / 2; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return CN_ITER * 2; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return CN_ITER * 2; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return 0x60000; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return 0x60000; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return 0xC000; } +template<> constexpr inline uint32_t CnAlgo::iterations() const { return CN_ITER / 8; } + + +template<> constexpr inline size_t CnAlgo::memory() const { return CN_MEMORY / 2; } +template<> constexpr inline size_t CnAlgo::memory() const { return CN_MEMORY / 2; } +template<> constexpr inline size_t CnAlgo::memory() const { return CN_MEMORY * 2; } +template<> constexpr inline size_t CnAlgo::memory() const { return CN_MEMORY * 2; } +template<> constexpr inline size_t CnAlgo::memory() const { return CN_MEMORY * 2; } +template<> constexpr inline size_t CnAlgo::memory() const { return CN_MEMORY / 8; } + + +template<> constexpr inline uint32_t CnAlgo::mask() const { return 0x1FFFC0; } +template<> constexpr inline uint32_t CnAlgo::mask() const { return 0x1FFF0; } } /* namespace xmrig */ diff --git a/src/crypto/common/Algorithm.cpp b/src/crypto/common/Algorithm.cpp index 6b5e32c76..bf04911c4 100644 --- a/src/crypto/common/Algorithm.cpp +++ b/src/crypto/common/Algorithm.cpp @@ -24,24 +24,21 @@ */ -#include -#include -#include -#include +#include "crypto/common/Algorithm.h" #include "crypto/cn/CnAlgo.h" -#include "crypto/common/Algorithm.h" #include "rapidjson/document.h" -#ifdef _MSC_VER -# define strcasecmp _stricmp -#endif +#include +#include +#include +#include -#ifndef ARRAY_SIZE -# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#ifdef _MSC_VER +# define strcasecmp _stricmp #endif @@ -67,7 +64,6 @@ static AlgoName const algorithm_names[] = { { "cryptonight_v8", nullptr, Algorithm::CN_2 }, { "cryptonight/r", "cn/r", Algorithm::CN_R }, { "cryptonight_r", nullptr, Algorithm::CN_R }, - { "cryptonight/wow", "cn/wow", Algorithm::CN_WOW }, { "cryptonight/fast", "cn/fast", Algorithm::CN_FAST }, { "cryptonight/msr", "cn/msr", Algorithm::CN_FAST }, { "cryptonight/half", "cn/half", Algorithm::CN_HALF }, @@ -114,6 +110,8 @@ static AlgoName const algorithm_names[] = { { "RandomWOW", nullptr, Algorithm::RX_WOW }, { "randomx/loki", "rx/loki", Algorithm::RX_LOKI }, { "RandomXL", nullptr, Algorithm::RX_LOKI }, + { "randomx/arq", "rx/arq", Algorithm::RX_ARQ }, + { "RandomARQ", nullptr, Algorithm::RX_ARQ }, # endif # ifdef XMRIG_ALGO_ARGON2 { "argon2/chukwa", nullptr, Algorithm::AR2_CHUKWA }, @@ -145,6 +143,9 @@ size_t xmrig::Algorithm::l2() const case RX_WOW: return 0x20000; + case RX_ARQ: + return 0x10000; + default: break; } @@ -175,6 +176,9 @@ size_t xmrig::Algorithm::l3() const case RX_WOW: return oneMiB; + case RX_ARQ: + return oneMiB / 4; + default: break; } @@ -231,7 +235,6 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id) case CN_1: case CN_2: case CN_R: - case CN_WOW: case CN_FAST: case CN_HALF: case CN_XAO: @@ -266,6 +269,7 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id) case RX_0: case RX_WOW: case RX_LOKI: + case RX_ARQ: return RANDOM_X; # endif @@ -275,9 +279,8 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id) return ARGON2; # endif - case INVALID: - case MAX: - return UNKNOWN; + default: + break; } return UNKNOWN; @@ -290,9 +293,9 @@ xmrig::Algorithm::Id xmrig::Algorithm::parse(const char *name) return INVALID; } - for (size_t i = 0; i < ARRAY_SIZE(algorithm_names); i++) { - if ((strcasecmp(name, algorithm_names[i].name) == 0) || (algorithm_names[i].shortName != nullptr && strcasecmp(name, algorithm_names[i].shortName) == 0)) { - return algorithm_names[i].id; + for (const AlgoName &item : algorithm_names) { + if ((strcasecmp(name, item.name) == 0) || (item.shortName != nullptr && strcasecmp(name, item.shortName) == 0)) { + return item.id; } } @@ -302,9 +305,9 @@ xmrig::Algorithm::Id xmrig::Algorithm::parse(const char *name) const char *xmrig::Algorithm::name(bool shortName) const { - for (size_t i = 0; i < ARRAY_SIZE(algorithm_names); i++) { - if (algorithm_names[i].id == m_id) { - return (shortName && algorithm_names[i].shortName) ? algorithm_names[i].shortName : algorithm_names[i].name; + for (const AlgoName &item : algorithm_names) { + if (item.id == m_id) { + return (shortName && item.shortName) ? item.shortName : item.name; } } diff --git a/src/crypto/common/Algorithm.h b/src/crypto/common/Algorithm.h index 5226133d8..0c6f2649a 100644 --- a/src/crypto/common/Algorithm.h +++ b/src/crypto/common/Algorithm.h @@ -39,13 +39,16 @@ namespace xmrig { class Algorithm { public: + // Changes in following file is required if this enum changed: + // + // src/backend/opencl/cl/cn/algorithm.cl + // enum Id : int { INVALID = -1, CN_0, // "cn/0" CryptoNight (original). CN_1, // "cn/1" CryptoNight variant 1 also known as Monero7 and CryptoNightV7. CN_2, // "cn/2" CryptoNight variant 2. CN_R, // "cn/r" CryptoNightR (Monero's variant 4). - CN_WOW, // "cn/wow" CryptoNightR (Wownero). CN_FAST, // "cn/fast" CryptoNight variant 1 with half iterations. CN_HALF, // "cn/half" CryptoNight variant 2 with half iterations (Masari/Torque). CN_XAO, // "cn/xao" CryptoNight variant 0 (modified, Alloy only). @@ -53,30 +56,19 @@ class Algorithm CN_RWZ, // "cn/rwz" CryptoNight variant 2 with 3/4 iterations and reversed shuffle operation (Graft). CN_ZLS, // "cn/zls" CryptoNight variant 2 with 3/4 iterations (Zelerius). CN_DOUBLE, // "cn/double" CryptoNight variant 2 with double iterations (X-CASH). -# ifdef XMRIG_ALGO_CN_GPU CN_GPU, // "cn/gpu" CryptoNight-GPU (Ryo). -# endif -# ifdef XMRIG_ALGO_CN_LITE CN_LITE_0, // "cn-lite/0" CryptoNight-Lite variant 0. CN_LITE_1, // "cn-lite/1" CryptoNight-Lite variant 1. -# endif -# ifdef XMRIG_ALGO_CN_HEAVY CN_HEAVY_0, // "cn-heavy/0" CryptoNight-Heavy (4 MB). CN_HEAVY_TUBE, // "cn-heavy/tube" CryptoNight-Heavy (modified, TUBE only). CN_HEAVY_XHV, // "cn-heavy/xhv" CryptoNight-Heavy (modified, Haven Protocol only). -# endif -# ifdef XMRIG_ALGO_CN_PICO CN_PICO_0, // "cn-pico" CryptoNight Turtle (TRTL) -# endif -# ifdef XMRIG_ALGO_RANDOMX RX_0, // "rx/0" RandomX (reference configuration). RX_WOW, // "rx/wow" RandomWOW (Wownero). RX_LOKI, // "rx/loki" RandomXL (Loki). -# endif -# ifdef XMRIG_ALGO_ARGON2 - AR2_CHUKWA, // "argon2/chukwa" - AR2_WRKZ, // "argon2/wrkz" -# endif + RX_ARQ, // "rx/arq" RandomARQ (Arqma). + AR2_CHUKWA, // "argon2/chukwa" Argon2id (Chukwa). + AR2_WRKZ, // "argon2/wrkz" Argon2id (WRKZ) MAX }; @@ -90,10 +82,11 @@ class Algorithm ARGON2 }; - inline Algorithm() {} + inline Algorithm() = default; inline Algorithm(const char *algo) : m_id(parse(algo)) {} inline Algorithm(Id id) : m_id(id) {} + inline bool isCN() const { auto f = family(); return f == CN || f == CN_LITE || f == CN_HEAVY || f == CN_PICO; } inline bool isEqual(const Algorithm &other) const { return m_id == other.m_id; } inline bool isValid() const { return m_id != INVALID; } inline const char *name() const { return name(false); } @@ -122,7 +115,7 @@ class Algorithm }; -typedef std::vector Algorithms; +using Algorithms = std::vector; } /* namespace xmrig */ diff --git a/src/crypto/common/Coin.cpp b/src/crypto/common/Coin.cpp index f5a32851a..32a1ff568 100644 --- a/src/crypto/common/Coin.cpp +++ b/src/crypto/common/Coin.cpp @@ -49,6 +49,8 @@ struct CoinName static CoinName const coin_names[] = { { "monero", Coin::MONERO }, { "xmr", Coin::MONERO }, + { "arqma", Coin::ARQMA }, + { "arq", Coin::ARQMA } }; @@ -58,8 +60,15 @@ static CoinName const coin_names[] = { xmrig::Algorithm::Id xmrig::Coin::algorithm(uint8_t blobVersion) const { - if (id() == MONERO) { + switch (id()) { + case MONERO: return (blobVersion >= 12) ? Algorithm::RX_0 : Algorithm::CN_R; + + case ARQMA: + return (blobVersion >= 15) ? Algorithm::RX_ARQ : Algorithm::CN_PICO_0; + + case INVALID: + break; } return Algorithm::INVALID; diff --git a/src/crypto/common/Coin.h b/src/crypto/common/Coin.h index 779d60b81..3df3784bb 100644 --- a/src/crypto/common/Coin.h +++ b/src/crypto/common/Coin.h @@ -40,6 +40,7 @@ class Coin enum Id : int { INVALID = -1, MONERO, + ARQMA }; From 072638b5c6bcd385b523171392fdc496fc9f116b Mon Sep 17 00:00:00 2001 From: XMRig Date: Fri, 1 Nov 2019 21:50:18 +0700 Subject: [PATCH 4/7] Sync changes with miner. --- src/base/io/log/Log.h | 2 ++ src/base/kernel/interfaces/IConfig.h | 4 ++++ src/base/net/stratum/Client.cpp | 4 ++-- src/base/net/stratum/DaemonClient.cpp | 4 ++-- src/base/net/stratum/Job.cpp | 32 +++++++++++++++++++++++++++ src/base/net/stratum/Job.h | 15 ++++++++++--- src/base/net/stratum/Pool.cpp | 1 + src/base/net/stratum/SubmitResult.h | 4 +++- 8 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/base/io/log/Log.h b/src/base/io/log/Log.h index 3517b61d4..cfd3c3a33 100644 --- a/src/base/io/log/Log.h +++ b/src/base/io/log/Log.h @@ -82,6 +82,7 @@ class Log #define WHITE_S CSI "0;37m" // another name for LT.GRAY #define WHITE_BOLD_S CSI "1;37m" // actually white +#define GREEN_BG_BOLD_S CSI "42;1m" #define BLUE_BG_S CSI "44m" #define BLUE_BG_BOLD_S CSI "44;1m" #define MAGENTA_BG_S CSI "45m" @@ -107,6 +108,7 @@ class Log #define WHITE(x) WHITE_S x CLEAR #define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR +#define GREEN_BG_BOLD(x) GREEN_BG_BOLD_S x CLEAR #define BLUE_BG(x) BLUE_BG_S x CLEAR #define BLUE_BG_BOLD(x) BLUE_BG_BOLD_S x CLEAR #define MAGENTA_BG(x) MAGENTA_BG_S x CLEAR diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 9f8d96180..7167e0bb7 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -134,6 +134,10 @@ class IConfig CudaLaunchKey = 1204, CudaAffinityKey = 1205, CudaMaxUsageKey = 1206, + CudaKey = 1207, + CudaLoaderKey = 1208, + NvmlKey = 1209, + HealthPrintTimeKey = 1210, }; virtual ~IConfig() = default; diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 3619e4e9f..9729f3fbc 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -212,9 +212,9 @@ int64_t xmrig::Client::submit(const JobResult &result) JsonRequest::create(doc, m_sequence, "submit", params); # ifdef XMRIG_PROXY_PROJECT - m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id); + m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id, 0); # else - m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff()); + m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), 0, result.backend); # endif return send(doc); diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 0870dc1db..09f2a7f90 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -117,9 +117,9 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result) JsonRequest::create(doc, m_sequence, "submitblock", params); # ifdef XMRIG_PROXY_PROJECT - m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id); + m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id, 0); # else - m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff()); + m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), 0, result.backend); # endif send(HTTP_POST, kJsonRPC, doc); diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index ef1b03b59..1de1c19b1 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -157,6 +157,7 @@ void xmrig::Job::copy(const Job &other) m_size = other.m_size; m_clientId = other.m_clientId; m_id = other.m_id; + m_backend = other.m_backend; m_diff = other.m_diff; m_height = other.m_height; m_target = other.m_target; @@ -174,3 +175,34 @@ void xmrig::Job::copy(const Job &other) memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget)); # endif } + + +void xmrig::Job::move(Job &&other) +{ + m_algorithm = other.m_algorithm; + m_nicehash = other.m_nicehash; + m_size = other.m_size; + m_clientId = std::move(other.m_clientId); + m_id = std::move(other.m_id); + m_backend = other.m_backend; + m_diff = other.m_diff; + m_height = other.m_height; + m_target = other.m_target; + m_index = other.m_index; + m_seed = std::move(other.m_seed); + m_extraNonce = std::move(other.m_extraNonce); + m_poolWallet = std::move(other.m_poolWallet); + + memcpy(m_blob, other.m_blob, sizeof(m_blob)); + + other.m_size = 0; + other.m_diff = 0; + other.m_algorithm = Algorithm::INVALID; + +# ifdef XMRIG_PROXY_PROJECT + m_rawSeedHash = std::move(other.m_rawSeedHash); + + memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob)); + memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget)); +# endif +} diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 3c4c4724c..9e1f3bc98 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -50,6 +50,10 @@ class Job Job() = default; Job(bool nicehash, const Algorithm &algorithm, const String &clientId); + + inline Job(const Job &other) { copy(other); } + inline Job(Job &&other) noexcept { move(std::move(other)); } + ~Job() = default; bool isEqual(const Job &other) const; @@ -71,6 +75,7 @@ class Job inline const uint8_t *blob() const { return m_blob; } inline size_t size() const { return m_size; } inline uint32_t *nonce() { return reinterpret_cast(m_blob + 39); } + inline uint32_t backend() const { return m_backend; } inline uint64_t diff() const { return m_diff; } inline uint64_t height() const { return m_height; } inline uint64_t target() const { return m_target; } @@ -79,6 +84,7 @@ class Job inline void reset() { m_size = 0; m_diff = 0; } inline void setAlgorithm(const Algorithm::Id id) { m_algorithm = id; } inline void setAlgorithm(const char *algo) { m_algorithm = algo; } + inline void setBackend(uint32_t backend) { m_backend = backend; } inline void setClientId(const String &id) { m_clientId = id; } inline void setExtraNonce(const String &extraNonce) { m_extraNonce = extraNonce; } inline void setHeight(uint64_t height) { m_height = height; } @@ -95,12 +101,14 @@ class Job static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast(blob + 39); } static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; } - inline bool operator==(const Job &other) const { return isEqual(other); } inline bool operator!=(const Job &other) const { return !isEqual(other); } + inline bool operator==(const Job &other) const { return isEqual(other); } inline Job &operator=(const Job &other) { copy(other); return *this; } + inline Job &operator=(Job &&other) noexcept { move(std::move(other)); return *this; } private: void copy(const Job &other); + void move(Job &&other); Algorithm m_algorithm; bool m_nicehash = false; @@ -110,6 +118,7 @@ class Job String m_extraNonce; String m_id; String m_poolWallet; + uint32_t m_backend = 0; uint64_t m_diff = 0; uint64_t m_height = 0; uint64_t m_target = 0; @@ -117,8 +126,8 @@ class Job uint8_t m_index = 0; # ifdef XMRIG_PROXY_PROJECT - char m_rawBlob[kMaxBlobSize * 2 + 8]; - char m_rawTarget[24]; + char m_rawBlob[kMaxBlobSize * 2 + 8]{}; + char m_rawTarget[24]{}; String m_rawSeedHash; # endif }; diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index eb2fe5066..59b70b11f 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "base/net/stratum/Pool.h" diff --git a/src/base/net/stratum/SubmitResult.h b/src/base/net/stratum/SubmitResult.h index 1b49acb43..a180f6fa5 100644 --- a/src/base/net/stratum/SubmitResult.h +++ b/src/base/net/stratum/SubmitResult.h @@ -37,9 +37,10 @@ class SubmitResult public: SubmitResult() = default; - inline SubmitResult(int64_t seq, uint64_t diff, uint64_t actualDiff, int64_t reqId = 0) : + inline SubmitResult(int64_t seq, uint64_t diff, uint64_t actualDiff, int64_t reqId, uint32_t backend) : reqId(reqId), seq(seq), + backend(backend), actualDiff(actualDiff), diff(diff), m_start(Chrono::steadyMSecs()) @@ -49,6 +50,7 @@ class SubmitResult int64_t reqId = 0; int64_t seq = 0; + uint32_t backend = 0; uint64_t actualDiff = 0; uint64_t diff = 0; uint64_t elapsed = 0; From 4782b441e9146d1558a12a2b35f5c3043fe92ca9 Mon Sep 17 00:00:00 2001 From: xmrig Date: Sat, 2 Nov 2019 03:52:01 +0700 Subject: [PATCH 5/7] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e69b39853..99d231790 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v4.5.0-beta +- Proxy rebased to latest miner codebase. + - [#1068](https://github.com/xmrig/xmrig/pull/1068) Added support for `self-select` stratum protocol extension. + - [#1227](https://github.com/xmrig/xmrig/pull/1227) Added new algorithm `rx/arq`, RandomX variant for upcoming ArQmA fork. + # v3.2.1 - [#349](https://github.com/xmrig/xmrig-proxy/issues/349) Fixed command line option `--coin`. From 92ba6099a7feadd37ef349e595f5b59d06d44182 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sat, 2 Nov 2019 19:25:52 +0700 Subject: [PATCH 6/7] v4.5.0-beta --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index c9d6ecebf..dee36b1e8 100644 --- a/src/version.h +++ b/src/version.h @@ -28,14 +28,14 @@ #define APP_ID "xmrig-proxy" #define APP_NAME "xmrig-proxy" #define APP_DESC "XMRig Stratum proxy" -#define APP_VERSION "4.4.0-evo" +#define APP_VERSION "4.5.0-beta" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" #define APP_KIND "proxy" #define APP_VER_MAJOR 4 -#define APP_VER_MINOR 4 +#define APP_VER_MINOR 5 #define APP_VER_PATCH 0 #ifdef _MSC_VER From 054ecc64dfee4229d68c0d96e25f3b9b517a03ce Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 13 Nov 2019 13:44:05 +0700 Subject: [PATCH 7/7] v5.0.0-dev --- src/version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/version.h b/src/version.h index dee36b1e8..019376a32 100644 --- a/src/version.h +++ b/src/version.h @@ -28,14 +28,14 @@ #define APP_ID "xmrig-proxy" #define APP_NAME "xmrig-proxy" #define APP_DESC "XMRig Stratum proxy" -#define APP_VERSION "4.5.0-beta" +#define APP_VERSION "5.0.0-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com" #define APP_KIND "proxy" -#define APP_VER_MAJOR 4 -#define APP_VER_MINOR 5 +#define APP_VER_MAJOR 5 +#define APP_VER_MINOR 0 #define APP_VER_PATCH 0 #ifdef _MSC_VER