diff --git a/CHANGELOG.md b/CHANGELOG.md index ce58c88e..e6aaeea6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v4.2.0-beta +- [#1202](https://github.com/xmrig/xmrig/issues/1202) Fixed algorithm verification in donate strategy. +- Added per pool option `coin` with single possible value `monero` for pools without algorithm negotiation, for upcoming Monero fork. +- Added config option `cpu/max-threads-hint` and command line option `--cpu-max-threads-hint`. + # v4.1.0-beta - **OpenCL backend disabled by default.**. - [#1183](https://github.com/xmrig/xmrig/issues/1183) Fixed compatibility with systemd. diff --git a/CMakeLists.txt b/CMakeLists.txt index 850ddef8..377a0bf6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,7 @@ set(HEADERS_CRYPTO src/crypto/cn/skein_port.h src/crypto/cn/soft_aes.h src/crypto/common/Algorithm.h + src/crypto/common/Coin.h src/crypto/common/keccak.h src/crypto/common/Nonce.h src/crypto/common/portable/mm_malloc.h @@ -108,6 +109,7 @@ set(SOURCES_CRYPTO src/crypto/cn/CnCtx.cpp src/crypto/cn/CnHash.cpp src/crypto/common/Algorithm.cpp + src/crypto/common/Coin.cpp src/crypto/common/keccak.cpp src/crypto/common/Nonce.cpp src/crypto/common/VirtualMemory.cpp diff --git a/doc/CPU.md b/doc/CPU.md index 4d1f0858..66745a66 100644 --- a/doc/CPU.md +++ b/doc/CPU.md @@ -94,3 +94,6 @@ Enable/configure or disable ASM optimizations. Possible values: `true`, `false`, #### `argon2-impl` (since v3.1.0) Allow override automatically detected Argon2 implementation, this option added mostly for debug purposes, default value `null` means autodetect. Other possible values: `"x86_64"`, `"SSE2"`, `"SSSE3"`, `"XOP"`, `"AVX2"`, `"AVX-512F"`. Manual selection has no safe guards, if you CPU not support required instuctions, miner will crash. + +#### `max-threads-hint` (since v4.2.0) +Maximum CPU threads count (in percentage) hint for autoconfig. [CPU_MAX_USAGE.md](CPU_MAX_USAGE.md) diff --git a/doc/CPU_MAX_USAGE.md b/doc/CPU_MAX_USAGE.md new file mode 100644 index 00000000..fccfd456 --- /dev/null +++ b/doc/CPU_MAX_USAGE.md @@ -0,0 +1,26 @@ +# Maximum CPU usage + +Please read this document carefully, `max-threads-hint` (was known as `max-cpu-usage`) option is most confusing option in the miner with many myth and legends. +This option is just hint for automatic configuration and can't precise define CPU usage. + +### Option definition +#### Config file: +```json +{ + ... + "cpu": { + "max-threads-hint": 100, + ... + }, + ... +} +``` + +#### Command line +`--cpu-max-threads-hint 100` + +### Known issues and usage + +* This option has no effect if miner already generated CPU configuration, to prevent config generation use `"autosave":false,`. +* Only threads count can be changed, for 1 core CPU this option has no effect, for 2 core CPU only 2 values possible 50% and 100%, for 4 cores: 25%, 50%, 75%, 100%. etc. +* You CPU may limited by other factors, eg cache. diff --git a/src/backend/common/Threads.h b/src/backend/common/Threads.h index afae184c..f73b22a0 100644 --- a/src/backend/common/Threads.h +++ b/src/backend/common/Threads.h @@ -44,6 +44,7 @@ class Threads public: inline bool has(const char *profile) const { return m_profiles.count(profile) > 0; } inline bool isDisabled(const Algorithm &algo) const { return m_disabled.count(algo) > 0; } + inline bool isEmpty() const { return m_profiles.empty(); } inline bool isExist(const Algorithm &algo) const { return isDisabled(algo) || m_aliases.count(algo) > 0 || has(algo.shortName()); } inline const T &get(const Algorithm &algo, bool strict = false) const { return get(profileName(algo, strict)); } inline void disable(const Algorithm &algo) { m_disabled.insert(algo); } diff --git a/src/backend/cpu/CpuConfig.cpp b/src/backend/cpu/CpuConfig.cpp index 7ea6a38b..8a8a76c6 100644 --- a/src/backend/cpu/CpuConfig.cpp +++ b/src/backend/cpu/CpuConfig.cpp @@ -35,6 +35,7 @@ static const char *kCn = "cn"; static const char *kEnabled = "enabled"; static const char *kHugePages = "huge-pages"; static const char *kHwAes = "hw-aes"; +static const char *kMaxThreadsHint = "max-threads-hint"; static const char *kPriority = "priority"; #ifdef XMRIG_FEATURE_ASM @@ -72,11 +73,6 @@ extern template class Threads; } -xmrig::CpuConfig::CpuConfig() -{ -} - - bool xmrig::CpuConfig::isHwAES() const { return (m_aes == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aes) == AES_HW; @@ -95,6 +91,10 @@ rapidjson::Value xmrig::CpuConfig::toJSON(rapidjson::Document &doc) const obj.AddMember(StringRef(kHwAes), m_aes == AES_AUTO ? Value(kNullType) : Value(m_aes == AES_HW), allocator); obj.AddMember(StringRef(kPriority), priority() != -1 ? Value(priority()) : Value(kNullType), allocator); + if (m_threads.isEmpty()) { + obj.AddMember(StringRef(kMaxThreadsHint), m_limit, allocator); + } + # ifdef XMRIG_FEATURE_ASM obj.AddMember(StringRef(kAsm), m_assembly.toJSON(), allocator); # endif @@ -131,8 +131,9 @@ std::vector xmrig::CpuConfig::get(const Miner *miner, cons void xmrig::CpuConfig::read(const rapidjson::Value &value, uint32_t version) { if (value.IsObject()) { - m_enabled = Json::getBool(value, kEnabled, m_enabled); - m_hugePages = Json::getBool(value, kHugePages, m_hugePages); + m_enabled = Json::getBool(value, kEnabled, m_enabled); + m_hugePages = Json::getBool(value, kHugePages, m_hugePages); + m_limit = Json::getUint(value, kMaxThreadsHint, m_limit); setAesMode(Json::getValue(value, kHwAes)); setPriority(Json::getInt(value, kPriority, -1)); @@ -168,28 +169,28 @@ void xmrig::CpuConfig::generate() ICpuInfo *cpu = Cpu::info(); m_threads.disable(Algorithm::CN_0); - m_threads.move(kCn, cpu->threads(Algorithm::CN_0)); + m_threads.move(kCn, cpu->threads(Algorithm::CN_0, m_limit)); # ifdef XMRIG_ALGO_CN_GPU - m_threads.move(kCnGPU, cpu->threads(Algorithm::CN_GPU)); + m_threads.move(kCnGPU, cpu->threads(Algorithm::CN_GPU, m_limit)); # endif # ifdef XMRIG_ALGO_CN_LITE m_threads.disable(Algorithm::CN_LITE_0); - m_threads.move(kCnLite, cpu->threads(Algorithm::CN_LITE_1)); + m_threads.move(kCnLite, cpu->threads(Algorithm::CN_LITE_1, m_limit)); # endif # ifdef XMRIG_ALGO_CN_HEAVY - m_threads.move(kCnHeavy, cpu->threads(Algorithm::CN_HEAVY_0)); + m_threads.move(kCnHeavy, cpu->threads(Algorithm::CN_HEAVY_0, m_limit)); # endif # ifdef XMRIG_ALGO_CN_PICO - m_threads.move(kCnPico, cpu->threads(Algorithm::CN_PICO_0)); + m_threads.move(kCnPico, cpu->threads(Algorithm::CN_PICO_0, m_limit)); # endif # ifdef XMRIG_ALGO_RANDOMX - m_threads.move(kRx, cpu->threads(Algorithm::RX_0)); - m_threads.move(kRxWOW, cpu->threads(Algorithm::RX_WOW)); + m_threads.move(kRx, cpu->threads(Algorithm::RX_0, m_limit)); + m_threads.move(kRxWOW, cpu->threads(Algorithm::RX_WOW, m_limit)); # endif generateArgon2(); @@ -199,7 +200,7 @@ void xmrig::CpuConfig::generate() void xmrig::CpuConfig::generateArgon2() { # ifdef XMRIG_ALGO_ARGON2 - m_threads.move(kArgon2, Cpu::info()->threads(Algorithm::AR2_CHUKWA)); + m_threads.move(kArgon2, Cpu::info()->threads(Algorithm::AR2_CHUKWA, m_limit)); # endif } diff --git a/src/backend/cpu/CpuConfig.h b/src/backend/cpu/CpuConfig.h index 67010eea..27075425 100644 --- a/src/backend/cpu/CpuConfig.h +++ b/src/backend/cpu/CpuConfig.h @@ -44,7 +44,7 @@ public: AES_SOFT }; - CpuConfig(); + CpuConfig() = default; bool isHwAES() const; rapidjson::Value toJSON(rapidjson::Document &doc) const; @@ -74,6 +74,7 @@ private: int m_priority = -1; String m_argon2Impl; Threads m_threads; + uint32_t m_limit = 100; }; diff --git a/src/backend/cpu/interfaces/ICpuInfo.h b/src/backend/cpu/interfaces/ICpuInfo.h index 9bc3b11a..20e72391 100644 --- a/src/backend/cpu/interfaces/ICpuInfo.h +++ b/src/backend/cpu/interfaces/ICpuInfo.h @@ -45,18 +45,18 @@ public: inline constexpr static bool isX64() { return false; } # endif - virtual Assembly::Id assembly() const = 0; - virtual bool hasAES() const = 0; - virtual bool hasAVX2() const = 0; - virtual const char *backend() const = 0; - virtual const char *brand() const = 0; - virtual CpuThreads threads(const Algorithm &algorithm) const = 0; - virtual size_t cores() const = 0; - virtual size_t L2() const = 0; - virtual size_t L3() const = 0; - virtual size_t nodes() const = 0; - virtual size_t packages() const = 0; - virtual size_t threads() const = 0; + virtual Assembly::Id assembly() const = 0; + virtual bool hasAES() const = 0; + virtual bool hasAVX2() const = 0; + virtual const char *backend() const = 0; + virtual const char *brand() const = 0; + virtual CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const = 0; + virtual size_t cores() const = 0; + virtual size_t L2() const = 0; + virtual size_t L3() const = 0; + virtual size_t nodes() const = 0; + virtual size_t packages() const = 0; + virtual size_t threads() const = 0; }; diff --git a/src/backend/cpu/platform/AdvancedCpuInfo.cpp b/src/backend/cpu/platform/AdvancedCpuInfo.cpp index 26798895..5cae55e2 100644 --- a/src/backend/cpu/platform/AdvancedCpuInfo.cpp +++ b/src/backend/cpu/platform/AdvancedCpuInfo.cpp @@ -23,10 +23,10 @@ */ #include -#include -#include -#include -#include +#include +#include +#include +#include #include "3rdparty/libcpuid/libcpuid.h" @@ -109,7 +109,7 @@ xmrig::AdvancedCpuInfo::AdvancedCpuInfo() : } -xmrig::CpuThreads xmrig::AdvancedCpuInfo::threads(const Algorithm &algorithm) const +xmrig::CpuThreads xmrig::AdvancedCpuInfo::threads(const Algorithm &algorithm, uint32_t limit) const { if (threads() == 1) { return 1; @@ -153,5 +153,12 @@ xmrig::CpuThreads xmrig::AdvancedCpuInfo::threads(const Algorithm &algorithm) co } # endif - return CpuThreads(std::max(std::min(count, threads()), 1), intensity); + if (limit > 0 && limit < 100) { + count = std::min(count, static_cast(round(threads() * (limit / 100.0)))); + } + else { + count = std::min(count, threads()); + } + + return CpuThreads(std::max(count, 1), intensity); } diff --git a/src/backend/cpu/platform/AdvancedCpuInfo.h b/src/backend/cpu/platform/AdvancedCpuInfo.h index 51b84c9f..e2909a91 100644 --- a/src/backend/cpu/platform/AdvancedCpuInfo.h +++ b/src/backend/cpu/platform/AdvancedCpuInfo.h @@ -38,7 +38,7 @@ public: AdvancedCpuInfo(); protected: - CpuThreads threads(const Algorithm &algorithm) const override; + CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const override; inline Assembly::Id assembly() const override { return m_assembly; } inline bool hasAES() const override { return m_aes; } diff --git a/src/backend/cpu/platform/BasicCpuInfo.cpp b/src/backend/cpu/platform/BasicCpuInfo.cpp index 15ac8f40..db3741ee 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.cpp +++ b/src/backend/cpu/platform/BasicCpuInfo.cpp @@ -179,7 +179,7 @@ const char *xmrig::BasicCpuInfo::backend() const } -xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm) const +xmrig::CpuThreads xmrig::BasicCpuInfo::threads(const Algorithm &algorithm, uint32_t limit) const { const size_t count = std::thread::hardware_concurrency(); diff --git a/src/backend/cpu/platform/BasicCpuInfo.h b/src/backend/cpu/platform/BasicCpuInfo.h index 6cf25714..4c68c5f8 100644 --- a/src/backend/cpu/platform/BasicCpuInfo.h +++ b/src/backend/cpu/platform/BasicCpuInfo.h @@ -39,7 +39,7 @@ public: protected: const char *backend() const override; - CpuThreads threads(const Algorithm &algorithm) const override; + CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const override; inline Assembly::Id assembly() const override { return m_assembly; } inline bool hasAES() const override { return m_aes; } diff --git a/src/backend/cpu/platform/HwlocCpuInfo.cpp b/src/backend/cpu/platform/HwlocCpuInfo.cpp index 9e503742..e87faf2d 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.cpp +++ b/src/backend/cpu/platform/HwlocCpuInfo.cpp @@ -29,6 +29,7 @@ #include +#include #include @@ -127,9 +128,7 @@ static inline bool isCacheExclusive(hwloc_obj_t obj) } // namespace xmrig -xmrig::HwlocCpuInfo::HwlocCpuInfo() : BasicCpuInfo(), - m_backend(), - m_cache() +xmrig::HwlocCpuInfo::HwlocCpuInfo() { m_threads = 0; @@ -149,7 +148,7 @@ xmrig::HwlocCpuInfo::HwlocCpuInfo() : BasicCpuInfo(), # endif const std::vector packages = findByType(hwloc_get_root_obj(m_topology), HWLOC_OBJ_PACKAGE); - if (packages.size()) { + if (!packages.empty()) { const char *value = hwloc_obj_get_info_by_name(packages[0], "CPUModel"); if (value) { strncpy(m_brand, value, 64); @@ -202,10 +201,10 @@ xmrig::HwlocCpuInfo::~HwlocCpuInfo() } -xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm) const +xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm, uint32_t limit) const { if (L2() == 0 && L3() == 0) { - return BasicCpuInfo::threads(algorithm); + return BasicCpuInfo::threads(algorithm, limit); } const unsigned depth = L3() > 0 ? 3 : 2; @@ -218,21 +217,37 @@ xmrig::CpuThreads xmrig::HwlocCpuInfo::threads(const Algorithm &algorithm) const findCache(hwloc_get_root_obj(m_topology), depth, depth, [&caches](hwloc_obj_t found) { caches.emplace_back(found); }); - for (hwloc_obj_t cache : caches) { - processTopLevelCache(cache, algorithm, threads); + if (limit > 0 && limit < 100 && !caches.empty()) { + const double maxTotalThreads = round(m_threads * (limit / 100.0)); + const auto maxPerCache = std::max(static_cast(round(maxTotalThreads / caches.size())), 1); + int remaining = std::max(static_cast(maxTotalThreads), 1); + + for (hwloc_obj_t cache : caches) { + processTopLevelCache(cache, algorithm, threads, std::min(maxPerCache, remaining)); + + remaining -= maxPerCache; + if (remaining <= 0) { + break; + } + } + } + else { + for (hwloc_obj_t cache : caches) { + processTopLevelCache(cache, algorithm, threads, 0); + } } if (threads.isEmpty()) { LOG_WARN("hwloc auto configuration for algorithm \"%s\" failed.", algorithm.shortName()); - return BasicCpuInfo::threads(algorithm); + return BasicCpuInfo::threads(algorithm, limit); } return threads; } -void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorithm &algorithm, CpuThreads &threads) const +void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorithm &algorithm, CpuThreads &threads, size_t limit) const { constexpr size_t oneMiB = 1024u * 1024u; @@ -296,6 +311,10 @@ void xmrig::HwlocCpuInfo::processTopLevelCache(hwloc_obj_t cache, const Algorith } # endif + if (limit > 0) { + cacheHashes = std::min(cacheHashes, limit); + } + if (cacheHashes >= PUs) { for (hwloc_obj_t core : cores) { const std::vector units = findByType(core, HWLOC_OBJ_PU); diff --git a/src/backend/cpu/platform/HwlocCpuInfo.h b/src/backend/cpu/platform/HwlocCpuInfo.h index 340864f5..ec4aea2c 100644 --- a/src/backend/cpu/platform/HwlocCpuInfo.h +++ b/src/backend/cpu/platform/HwlocCpuInfo.h @@ -27,10 +27,11 @@ #include "backend/cpu/platform/BasicCpuInfo.h" +#include "base/tools/Object.h" -typedef struct hwloc_obj *hwloc_obj_t; -typedef struct hwloc_topology *hwloc_topology_t; +using hwloc_obj_t = struct hwloc_obj *; +using hwloc_topology_t = struct hwloc_topology *; namespace xmrig { @@ -39,6 +40,9 @@ namespace xmrig { class HwlocCpuInfo : public BasicCpuInfo { public: + XMRIG_DISABLE_COPY_MOVE(HwlocCpuInfo) + + enum Feature : uint32_t { SET_THISTHREAD_MEMBIND = 1 }; @@ -51,7 +55,7 @@ public: static inline const std::vector &nodeIndexes() { return m_nodeIndexes; } protected: - CpuThreads threads(const Algorithm &algorithm) const override; + CpuThreads threads(const Algorithm &algorithm, uint32_t limit) const override; inline const char *backend() const override { return m_backend; } inline size_t cores() const override { return m_cores; } @@ -61,17 +65,17 @@ protected: inline size_t packages() const override { return m_packages; } private: - void processTopLevelCache(hwloc_obj_t obj, const Algorithm &algorithm, CpuThreads &threads) const; + void processTopLevelCache(hwloc_obj_t obj, const Algorithm &algorithm, CpuThreads &threads, size_t limit) const; static std::vector m_nodeIndexes; static uint32_t m_features; - char m_backend[20]; - hwloc_topology_t m_topology; - size_t m_cache[5]; - size_t m_cores = 0; - size_t m_nodes = 0; - size_t m_packages = 0; + char m_backend[20] = { 0 }; + hwloc_topology_t m_topology = nullptr; + size_t m_cache[5] = { 0 }; + size_t m_cores = 0; + size_t m_nodes = 0; + size_t m_packages = 0; }; diff --git a/src/backend/opencl/wrappers/OclDevice.cpp b/src/backend/opencl/wrappers/OclDevice.cpp index b10713d4..67f8166b 100644 --- a/src/backend/opencl/wrappers/OclDevice.cpp +++ b/src/backend/opencl/wrappers/OclDevice.cpp @@ -59,7 +59,7 @@ extern bool ocl_vega_cn_generator(const OclDevice &device, const Algorithm &algo extern bool ocl_generic_cn_generator(const OclDevice &device, const Algorithm &algorithm, OclThreads &threads); -ocl_gen_config_fun generators[] = { +static ocl_gen_config_fun generators[] = { # ifdef XMRIG_ALGO_RANDOMX ocl_generic_rx_generator, # endif @@ -215,6 +215,6 @@ void xmrig::OclDevice::toJSON(rapidjson::Value &out, rapidjson::Document &doc) c out.AddMember("name", name().toJSON(doc), allocator); out.AddMember("bus_id", topology().toString().toJSON(doc), allocator); out.AddMember("cu", computeUnits(), allocator); - out.AddMember("global_mem", globalMemSize(), allocator); + out.AddMember("global_mem", static_cast(globalMemSize()), allocator); } #endif diff --git a/src/backend/opencl/wrappers/OclPlatform.cpp b/src/backend/opencl/wrappers/OclPlatform.cpp index 987ec5e3..601ee6fa 100644 --- a/src/backend/opencl/wrappers/OclPlatform.cpp +++ b/src/backend/opencl/wrappers/OclPlatform.cpp @@ -73,7 +73,7 @@ rapidjson::Value xmrig::OclPlatform::toJSON(rapidjson::Document &doc) const } Value out(kObjectType); - out.AddMember("index", index(), allocator); + out.AddMember("index", static_cast(index()), allocator); out.AddMember("profile", profile().toJSON(doc), allocator); out.AddMember("version", version().toJSON(doc), allocator); out.AddMember("name", name().toJSON(doc), allocator); diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index bd43036c..2f629bca 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -47,6 +47,7 @@ namespace xmrig static const char *kAlgo = "algo"; static const char *kApi = "api"; +static const char *kCoin = "coin"; static const char *kHttp = "http"; static const char *kPools = "pools"; @@ -103,6 +104,15 @@ void xmrig::BaseTransform::finalize(rapidjson::Document &doc) } } + if (m_coin.isValid() && doc.HasMember(kPools)) { + auto &pools = doc[kPools]; + for (Value &pool : pools.GetArray()) { + if (!pool.HasMember(kCoin)) { + pool.AddMember(StringRef(kCoin), m_coin.toJSON(), allocator); + } + } + } + if (m_http) { set(doc, kHttp, "enabled", true); } @@ -121,6 +131,15 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch } break; + case IConfig::CoinKey: /* --coin */ + if (!doc.HasMember(kPools)) { + m_coin = arg; + } + else { + return add(doc, kPools, kCoin, arg); + } + break; + case IConfig::UserpassKey: /* --userpass */ { const char *p = strrchr(arg, ':'); diff --git a/src/base/kernel/config/BaseTransform.h b/src/base/kernel/config/BaseTransform.h index f926861d..704f0899 100644 --- a/src/base/kernel/config/BaseTransform.h +++ b/src/base/kernel/config/BaseTransform.h @@ -27,6 +27,7 @@ #include "base/kernel/interfaces/IConfigTransform.h" +#include "crypto/common/Coin.h" #include "rapidjson/document.h" @@ -97,6 +98,7 @@ protected: protected: Algorithm m_algorithm; + Coin m_coin; private: diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 7823d325..8798de5f 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -43,6 +43,7 @@ public: enum Keys { // common AlgorithmKey = 'a', + CoinKey = 1025, ApiWorkerIdKey = 4002, ApiIdKey = 4005, HttpPort = 4100, @@ -87,6 +88,7 @@ public: AssemblyKey = 1015, RandomXInitKey = 1022, RandomXNumaKey = 1023, + CPUMaxThreadsKey = 1026, // xmrig amd OclPlatformKey = 1400, diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index b87466ab..b9189247 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -334,6 +334,9 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) if (algo) { job.setAlgorithm(algo); } + else if (m_pool.coin().isValid()) { + job.setAlgorithm(m_pool.coin().algorithm(job.blob()[0])); + } job.setHeight(Json::getUint64(params, "height")); @@ -426,7 +429,12 @@ bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm, const char *algo { if (!algorithm.isValid()) { if (!isQuiet()) { - LOG_ERR("[%s] Unknown/unsupported algorithm \"%s\" detected, reconnect", url(), algo); + if (algo == nullptr) { + LOG_ERR("[%s] unknown algorithm, make sure you set \"algo\" or \"coin\" option", url(), algo); + } + else { + LOG_ERR("[%s] unsupported algorithm \"%s\" detected, reconnect", url(), algo); + } } return false; @@ -436,7 +444,7 @@ bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm, const char *algo m_listener->onVerifyAlgorithm(this, algorithm, &ok); if (!ok && !isQuiet()) { - LOG_ERR("[%s] Incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algorithm.shortName()); + LOG_ERR("[%s] incompatible/disabled algorithm \"%s\" detected, reconnect", url(), algorithm.shortName()); } return ok; diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 0c141c7d..0870dc1d 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -25,7 +25,7 @@ #include -#include +#include #include "3rdparty/http-parser/http_parser.h" @@ -225,6 +225,10 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) job.setDiff(Json::getUint64(params, "difficulty")); job.setId(blocktemplate.data() + blocktemplate.size() - 32); + if (m_pool.coin().isValid()) { + job.setAlgorithm(m_pool.coin().algorithm(job.blob()[0])); + } + m_job = std::move(job); m_blocktemplate = std::move(blocktemplate); m_prevHash = Json::getString(params, "prev_hash"); diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index eafd10e3..d695c561 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -75,6 +75,7 @@ public: 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; } diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index ba31c35d..15586fe8 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -48,6 +48,7 @@ namespace xmrig { static const char *kAlgo = "algo"; +static const char *kCoin = "coin"; static const char *kDaemon = "daemon"; static const char *kDaemonPollInterval = "daemon-poll-interval"; static const char *kEnabled = "enabled"; @@ -120,6 +121,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) : m_fingerprint = Json::getString(object, kFingerprint); m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval); m_algorithm = Json::getString(object, kAlgo); + m_coin = Json::getString(object, kCoin); m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true)); m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash)); @@ -172,7 +174,7 @@ bool xmrig::Pool::isEnabled() const } # endif - if (isDaemon() && !algorithm().isValid()) { + if (isDaemon() && (!algorithm().isValid() && !coin().isValid())) { return false; } @@ -186,6 +188,7 @@ bool xmrig::Pool::isEqual(const Pool &other) const && m_keepAlive == other.m_keepAlive && m_port == other.m_port && m_algorithm == other.m_algorithm + && m_coin == other.m_coin && m_fingerprint == other.m_fingerprint && m_host == other.m_host && m_password == other.m_password @@ -268,6 +271,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const Value obj(kObjectType); 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(kUser), m_user.toJSON(), allocator); diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index 36c3ed1b..15d31ccc 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -32,7 +32,7 @@ #include "base/tools/String.h" -#include "crypto/common/Algorithm.h" +#include "crypto/common/Coin.h" #include "rapidjson/fwd.h" @@ -74,6 +74,7 @@ public: inline bool isTLS() const { return m_flags.test(FLAG_TLS); } inline bool isValid() const { return !m_host.isNull() && m_port > 0; } 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 &password() const { return !m_password.isNull() ? m_password : kDefaultPassword; } @@ -107,6 +108,7 @@ private: bool parseIPv6(const char *addr); Algorithm m_algorithm; + Coin m_coin; int m_keepAlive; std::bitset m_flags; String m_fingerprint; diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp index 4641ecd4..600c97ed 100644 --- a/src/base/net/stratum/Pools.cpp +++ b/src/base/net/stratum/Pools.cpp @@ -135,11 +135,12 @@ 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 " algo " WHITE_BOLD("%s"), + 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.algorithm().isValid() ? pool.algorithm().shortName() : "auto" + pool.coin().isValid() ? "coin" : "algo", + pool.coin().isValid() ? pool.coin().name() : (pool.algorithm().isValid() ? pool.algorithm().shortName() : "auto") ); i++; diff --git a/src/config.json b/src/config.json index 3023d22a..ec8ac419 100644 --- a/src/config.json +++ b/src/config.json @@ -23,6 +23,7 @@ "huge-pages": true, "hw-aes": null, "priority": null, + "max-threads-hint": 100, "asm": true, "argon2-impl": null, "cn/0": false, @@ -42,6 +43,7 @@ "pools": [ { "algo": null, + "coin": null, "url": "donate.v2.xmrig.com:3333", "user": "YOUR_WALLET_ADDRESS", "pass": "x", diff --git a/src/core/Miner.cpp b/src/core/Miner.cpp index d5372422..b6b89948 100644 --- a/src/core/Miner.cpp +++ b/src/core/Miner.cpp @@ -97,7 +97,7 @@ public: bool isEnabled(const Algorithm &algorithm) const { for (IBackend *backend : backends) { - if (backend->isEnabled(algorithm)) { + if (backend->isEnabled() && backend->isEnabled(algorithm)) { return true; } } diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index e7bd383f..3bdbcac5 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -138,6 +138,9 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const return transformUint64(doc, key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10)); } + case IConfig::CPUMaxThreadsKey: /* --cpu-max-threads-hint */ + return set(doc, kCpu, "max-threads-hint", static_cast(strtol(arg, nullptr, 10))); + # ifdef XMRIG_FEATURE_ASM case IConfig::AssemblyKey: /* --asm */ return set(doc, kCpu, "asm", arg); diff --git a/src/core/config/Config_default.h b/src/core/config/Config_default.h index b6816649..00c4cf12 100644 --- a/src/core/config/Config_default.h +++ b/src/core/config/Config_default.h @@ -57,6 +57,7 @@ R"===( "huge-pages": true, "hw-aes": null, "priority": null, + "max-threads-hint": 100, "asm": true, "argon2-impl": null, "cn/0": false, @@ -76,6 +77,7 @@ R"===( "pools": [ { "algo": null, + "coin": null, "url": "donate.v2.xmrig.com:3333", "user": "YOUR_WALLET_ADDRESS", "pass": "x", diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index e58a9fb7..b7f15daa 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -45,6 +45,7 @@ static const char short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:S"; static const option options[] = { { "algo", 1, nullptr, IConfig::AlgorithmKey }, + { "coin", 1, nullptr, IConfig::CoinKey }, # ifdef XMRIG_FEATURE_HTTP { "api-worker-id", 1, nullptr, IConfig::ApiWorkerIdKey }, { "api-id", 1, nullptr, IConfig::ApiIdKey }, @@ -81,6 +82,8 @@ static const option options[] = { { "userpass", 1, nullptr, IConfig::UserpassKey }, { "rig-id", 1, nullptr, IConfig::RigIdKey }, { "no-cpu", 0, nullptr, IConfig::CPUKey }, + { "max-cpu-usage", 1, nullptr, IConfig::CPUMaxThreadsKey }, + { "cpu-max-threads-hint", 1, nullptr, IConfig::CPUMaxThreadsKey }, # ifdef XMRIG_FEATURE_TLS { "tls", 0, nullptr, IConfig::TlsKey }, { "tls-fingerprint", 1, nullptr, IConfig::FingerprintKey }, diff --git a/src/core/config/usage.h b/src/core/config/usage.h index fc9695a3..0d7cdc5e 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -76,6 +76,7 @@ static inline const std::string &usage() u += " -v, --av=N algorithm variation, 0 auto select\n"; u += " --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n"; u += " --cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n"; + u += " --cpu-max-threads-hint=N maximum CPU threads count (in percentage) hint for autoconfig\n"; u += " --no-huge-pages disable huge pages support\n"; u += " --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer\n"; diff --git a/src/crypto/common/Algorithm.cpp b/src/crypto/common/Algorithm.cpp index eb1b1798..21883be6 100644 --- a/src/crypto/common/Algorithm.cpp +++ b/src/crypto/common/Algorithm.cpp @@ -103,9 +103,8 @@ static AlgoName const algorithm_names[] = { { "cryptonight_turtle", "cn_turtle", Algorithm::CN_PICO_0 }, # endif # ifdef XMRIG_ALGO_RANDOMX + { "randomx/0", "rx/0", Algorithm::RX_0 }, { "randomx/test", "rx/test", Algorithm::RX_0 }, - { "randomx/0", "rx/0", Algorithm::RX_0 }, - { "randomx/0", "rx/0", Algorithm::RX_0 }, { "RandomX", "rx", Algorithm::RX_0 }, { "randomx/wow", "rx/wow", Algorithm::RX_WOW }, { "RandomWOW", nullptr, Algorithm::RX_WOW }, diff --git a/src/crypto/common/Coin.cpp b/src/crypto/common/Coin.cpp new file mode 100644 index 00000000..f5a32851 --- /dev/null +++ b/src/crypto/common/Coin.cpp @@ -0,0 +1,103 @@ +/* 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 "crypto/common/Coin.h" +#include "rapidjson/document.h" + + +#include + + +#ifdef _MSC_VER +# define strcasecmp _stricmp +#endif + + +namespace xmrig { + + +struct CoinName +{ + const char *name; + const Coin::Id id; +}; + + +static CoinName const coin_names[] = { + { "monero", Coin::MONERO }, + { "xmr", Coin::MONERO }, +}; + + +} /* namespace xmrig */ + + + +xmrig::Algorithm::Id xmrig::Coin::algorithm(uint8_t blobVersion) const +{ + if (id() == MONERO) { + return (blobVersion >= 12) ? Algorithm::RX_0 : Algorithm::CN_R; + } + + return Algorithm::INVALID; +} + + + +const char *xmrig::Coin::name() const +{ + for (const auto &i : coin_names) { + if (i.id == m_id) { + return i.name; + } + } + + return nullptr; +} + + +rapidjson::Value xmrig::Coin::toJSON() const +{ + using namespace rapidjson; + + return isValid() ? Value(StringRef(name())) : Value(kNullType); +} + + +xmrig::Coin::Id xmrig::Coin::parse(const char *name) +{ + if (name == nullptr || strlen(name) < 3) { + return INVALID; + } + + for (const auto &i : coin_names) { + if (strcasecmp(name, i.name) == 0) { + return i.id; + } + } + + return INVALID; +} diff --git a/src/crypto/common/Coin.h b/src/crypto/common/Coin.h new file mode 100644 index 00000000..779d60b8 --- /dev/null +++ b/src/crypto/common/Coin.h @@ -0,0 +1,75 @@ +/* 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 . + */ + +#ifndef XMRIG_COIN_H +#define XMRIG_COIN_H + + +#include "crypto/common/Algorithm.h" +#include "rapidjson/fwd.h" + + +namespace xmrig { + + +class Coin +{ +public: + enum Id : int { + INVALID = -1, + MONERO, + }; + + + Coin() = default; + inline Coin(const char *name) : m_id(parse(name)) {} + inline Coin(Id id) : m_id(id) {} + + + inline bool isEqual(const Coin &other) const { return m_id == other.m_id; } + inline bool isValid() const { return m_id != INVALID; } + inline Id id() const { return m_id; } + + Algorithm::Id algorithm(uint8_t blobVersion) const; + const char *name() const; + rapidjson::Value toJSON() const; + + inline bool operator!=(Coin::Id id) const { return m_id != id; } + inline bool operator!=(const Coin &other) const { return !isEqual(other); } + inline bool operator==(Coin::Id id) const { return m_id == id; } + inline bool operator==(const Coin &other) const { return isEqual(other); } + inline operator Coin::Id() const { return m_id; } + + static Id parse(const char *name); + +private: + Id m_id = INVALID; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_COIN_H */ diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 2b3f4b5f..2fb40c6c 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -28,10 +28,10 @@ #endif #include -#include +#include +#include #include #include -#include #include "base/io/log/Log.h" @@ -83,11 +83,7 @@ xmrig::Network::~Network() JobResults::stop(); delete m_timer; - - if (m_donate) { - delete m_donate; - } - + delete m_donate; delete m_strategy; } @@ -304,8 +300,8 @@ void xmrig::Network::getResults(rapidjson::Value &reply, rapidjson::Document &do results.AddMember("hashes_total", m_state.total, allocator); Value best(kArrayType); - for (size_t i = 0; i < m_state.topDiff.size(); ++i) { - best.PushBack(m_state.topDiff[i], allocator); + for (uint64_t i : m_state.topDiff) { + best.PushBack(i, allocator); } results.AddMember("best", best, allocator); diff --git a/src/net/Network.h b/src/net/Network.h index 716ce610..7fd95e31 100644 --- a/src/net/Network.h +++ b/src/net/Network.h @@ -34,6 +34,7 @@ #include "base/kernel/interfaces/IBaseListener.h" #include "base/kernel/interfaces/IStrategyListener.h" #include "base/kernel/interfaces/ITimerListener.h" +#include "base/tools/Object.h" #include "interfaces/IJobResultListener.h" #include "net/NetworkState.h" #include "rapidjson/fwd.h" @@ -49,6 +50,8 @@ class IStrategy; class Network : public IJobResultListener, public IStrategyListener, public IBaseListener, public ITimerListener, public IApiListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(Network) + Network(Controller *controller); ~Network() override; diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 4393cd46..3952d94e 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -24,7 +24,7 @@ #include -#include +#include #include @@ -58,17 +58,10 @@ static const char *kDonateHostTls = "donate.ssl.xmrig.com"; xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener *listener) : - m_tls(false), - m_userId(), m_donateTime(static_cast(controller->config()->pools().donateLevel()) * 60 * 1000), m_idleTime((100 - static_cast(controller->config()->pools().donateLevel())) * 60 * 1000), m_controller(controller), - m_proxy(nullptr), - m_strategy(nullptr), - m_listener(listener), - m_state(STATE_NEW), - m_now(0), - m_timestamp(0) + m_listener(listener) { uint8_t hash[200]; @@ -77,15 +70,15 @@ xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener Buffer::toHex(hash, 32, m_userId); # ifdef XMRIG_FEATURE_TLS - m_pools.push_back(Pool(kDonateHostTls, 443, m_userId, nullptr, 0, true, true)); + m_pools.emplace_back(kDonateHostTls, 443, m_userId, nullptr, 0, true, true); # endif - m_pools.push_back(Pool(kDonateHost, 3333, m_userId, nullptr, 0, true)); + m_pools.emplace_back(kDonateHost, 3333, m_userId, nullptr, 0, true); if (m_pools.size() > 1) { - m_strategy = new FailoverStrategy(m_pools, 1, 2, this, true); + m_strategy = new FailoverStrategy(m_pools, 10, 2, this, true); } else { - m_strategy = new SinglePoolStrategy(m_pools.front(), 1, 2, this, true); + m_strategy = new SinglePoolStrategy(m_pools.front(), 10, 2, this, true); } m_timer = new Timer(this); @@ -223,6 +216,18 @@ void xmrig::DonateStrategy::onLoginSuccess(IClient *client) } +void xmrig::DonateStrategy::onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok) +{ + m_listener->onVerifyAlgorithm(this, client, algorithm, ok); +} + + +void xmrig::DonateStrategy::onVerifyAlgorithm(IStrategy *, const IClient *client, const Algorithm &algorithm, bool *ok) +{ + m_listener->onVerifyAlgorithm(this, client, algorithm, ok); +} + + void xmrig::DonateStrategy::onTimer(const Timer *) { setState(isActive() ? STATE_WAIT : STATE_CONNECT); @@ -246,7 +251,7 @@ xmrig::Client *xmrig::DonateStrategy::createProxy() Pool pool(client->ip(), client->pool().port(), m_userId, client->pool().password(), 0, true, client->isTLS()); pool.setAlgo(client->pool().algorithm()); - Client *proxy = new Client(-1, Platform::userAgent(), this); + auto proxy = new Client(-1, Platform::userAgent(), this); proxy->setPool(pool); proxy->setQuiet(true); diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index 134127bf..4c621f66 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -34,6 +34,7 @@ #include "base/kernel/interfaces/IStrategyListener.h" #include "base/kernel/interfaces/ITimerListener.h" #include "base/net/stratum/Pool.h" +#include "base/tools/Object.h" namespace xmrig { @@ -47,6 +48,8 @@ class IStrategyListener; class DonateStrategy : public IStrategy, public IStrategyListener, public ITimerListener, public IClientListener { public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(DonateStrategy) + DonateStrategy(Controller *controller, IStrategyListener *listener); ~DonateStrategy() override; @@ -57,8 +60,6 @@ protected: inline void onJobReceived(IClient *client, const Job &job, const rapidjson::Value &) override { setJob(client, job); } inline void onResultAccepted(IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } inline void onResultAccepted(IStrategy *, IClient *client, const SubmitResult &result, const char *error) override { setResult(client, result, error); } - inline void onVerifyAlgorithm(const IClient *, const Algorithm &, bool *) override {} - inline void onVerifyAlgorithm(IStrategy *, const IClient *, const Algorithm &, bool *) override {} inline void resume() override {} int64_t submit(const JobResult &result) override; @@ -74,6 +75,8 @@ protected: void onLogin(IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override; void onLogin(IStrategy *strategy, IClient *client, rapidjson::Document &doc, rapidjson::Value ¶ms) override; void onLoginSuccess(IClient *client) override; + void onVerifyAlgorithm(const IClient *client, const Algorithm &algorithm, bool *ok) override; + void onVerifyAlgorithm(IStrategy *strategy, const IClient *client, const Algorithm &algorithm, bool *ok) override; void onTimer(const Timer *timer) override; @@ -96,19 +99,19 @@ private: void setState(State state); Algorithm m_algorithm; - bool m_tls; - char m_userId[65]; + bool m_tls = false; + char m_userId[65] = { 0 }; const uint64_t m_donateTime; const uint64_t m_idleTime; Controller *m_controller; - IClient *m_proxy; - IStrategy *m_strategy; + IClient *m_proxy = nullptr; + IStrategy *m_strategy = nullptr; IStrategyListener *m_listener; - State m_state; + State m_state = STATE_NEW; std::vector m_pools; - Timer *m_timer; - uint64_t m_now; - uint64_t m_timestamp; + Timer *m_timer = nullptr; + uint64_t m_now = 0; + uint64_t m_timestamp = 0; }; diff --git a/src/version.h b/src/version.h index 5bf8e78c..eb4ac706 100644 --- a/src/version.h +++ b/src/version.h @@ -28,14 +28,14 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig miner" -#define APP_VERSION "4.1.0-beta" +#define APP_VERSION "4.2.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 "miner" #define APP_VER_MAJOR 4 -#define APP_VER_MINOR 1 +#define APP_VER_MINOR 2 #define APP_VER_PATCH 0 #ifdef _MSC_VER