diff --git a/src/base/api/Api.cpp b/src/base/api/Api.cpp index c66241c..c4b2c5a 100644 --- a/src/base/api/Api.cpp +++ b/src/base/api/Api.cpp @@ -31,10 +31,11 @@ #endif -#include "3rdparty/http-parser/http_parser.h" #include "base/api/Api.h" +#include "3rdparty/http-parser/http_parser.h" #include "base/api/interfaces/IApiListener.h" #include "base/api/requests/HttpApiRequest.h" +#include "base/io/json/Json.h" #include "base/kernel/Base.h" #include "base/tools/Buffer.h" #include "base/tools/Chrono.h" @@ -73,9 +74,10 @@ static rapidjson::Value getResources(rapidjson::Document &doc) double loadavg[3] = { 0.0 }; uv_loadavg(loadavg); - load_average.PushBack(loadavg[0], allocator); - load_average.PushBack(loadavg[1], allocator); - load_average.PushBack(loadavg[2], allocator); + + for (double value : loadavg) { + load_average.PushBack(Json::normalize(value, true), allocator); + } out.AddMember("memory", memory, allocator); out.AddMember("load_average", load_average, allocator); @@ -182,6 +184,9 @@ void xmrig::Api::exec(IApiRequest &request) # endif # ifdef XMRIG_FEATURE_OPENCL features.PushBack("opencl", allocator); +# endif +# ifdef XMRIG_FEATURE_CUDA + features.PushBack("cuda", allocator); # endif reply.AddMember("features", features, allocator); } diff --git a/src/base/io/json/Json.cpp b/src/base/io/json/Json.cpp index 9a57829..7386214 100644 --- a/src/base/io/json/Json.cpp +++ b/src/base/io/json/Json.cpp @@ -28,6 +28,7 @@ #include +#include namespace xmrig { @@ -154,6 +155,18 @@ unsigned xmrig::Json::getUint(const rapidjson::Value &obj, const char *key, unsi } +rapidjson::Value xmrig::Json::normalize(double value, bool zero) +{ + using namespace rapidjson; + + if (!std::isnormal(value)) { + return zero ? Value(0.0) : Value(kNullType); + } + + return Value(floor(value * 100.0) / 100.0); +} + + bool xmrig::JsonReader::isEmpty() const { return !m_obj.IsObject() || m_obj.ObjectEmpty(); diff --git a/src/base/io/json/Json.h b/src/base/io/json/Json.h index 80fe5dc..b5e2a3c 100644 --- a/src/base/io/json/Json.h +++ b/src/base/io/json/Json.h @@ -48,6 +48,8 @@ public: static bool get(const char *fileName, rapidjson::Document &doc); static bool save(const char *fileName, const rapidjson::Document &doc); + + static rapidjson::Value normalize(double value, bool zero); }; diff --git a/src/base/io/log/Log.h b/src/base/io/log/Log.h index cfd3c3a..c7e0c3f 100644 --- a/src/base/io/log/Log.h +++ b/src/base/io/log/Log.h @@ -83,6 +83,7 @@ private: #define WHITE_BOLD_S CSI "1;37m" // actually white #define GREEN_BG_BOLD_S CSI "42;1m" +#define YELLOW_BG_BOLD_S CSI "43;1m" #define BLUE_BG_S CSI "44m" #define BLUE_BG_BOLD_S CSI "44;1m" #define MAGENTA_BG_S CSI "45m" @@ -109,6 +110,7 @@ private: #define WHITE_BOLD(x) WHITE_BOLD_S x CLEAR #define GREEN_BG_BOLD(x) GREEN_BG_BOLD_S x CLEAR +#define YELLOW_BG_BOLD(x) YELLOW_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/io/log/backends/FileLog.cpp b/src/base/io/log/backends/FileLog.cpp index 1ff0163..c581b88 100644 --- a/src/base/io/log/backends/FileLog.cpp +++ b/src/base/io/log/backends/FileLog.cpp @@ -24,13 +24,14 @@ */ -#include -#include - - #include "base/io/log/backends/FileLog.h" +#include +#include +#include + + xmrig::FileLog::FileLog(const char *fileName) { uv_fs_t req; @@ -45,13 +46,12 @@ void xmrig::FileLog::print(int, const char *line, size_t, size_t size, bool colo return; } -# ifdef _WIN32 - uv_buf_t buf = uv_buf_init(strdup(line), static_cast(size)); -# else - uv_buf_t buf = uv_buf_init(strdup(line), size); -# endif + assert(strlen(line) == size); - uv_fs_t *req = new uv_fs_t; + uv_buf_t buf = uv_buf_init(new char[size], size); + memcpy(buf.base, line, size); + + auto req = new uv_fs_t; req->data = buf.base; uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, -1, FileLog::onWrite); diff --git a/src/base/kernel/Base.cpp b/src/base/kernel/Base.cpp index 90c7cb5..5718a11 100644 --- a/src/base/kernel/Base.cpp +++ b/src/base/kernel/Base.cpp @@ -176,10 +176,6 @@ int xmrig::Base::init() Platform::init(config()->userAgent()); -# ifndef XMRIG_PROXY_PROJECT - Platform::setProcessPriority(config()->cpu().priority()); -# endif - if (isBackground()) { Log::background = true; } diff --git a/src/base/kernel/Platform.h b/src/base/kernel/Platform.h index 3f026f8..fe39a69 100644 --- a/src/base/kernel/Platform.h +++ b/src/base/kernel/Platform.h @@ -51,7 +51,6 @@ public: static uint32_t setTimerResolution(uint32_t resolution); static void init(const char *userAgent); static void restoreTimerResolution(); - static void setProcessPriority(int priority); static void setThreadPriority(int priority); static inline const char *userAgent() { return m_userAgent; } diff --git a/src/base/kernel/Platform_mac.cpp b/src/base/kernel/Platform_mac.cpp index 146dd52..8d9bac3 100644 --- a/src/base/kernel/Platform_mac.cpp +++ b/src/base/kernel/Platform_mac.cpp @@ -83,11 +83,6 @@ void xmrig::Platform::restoreTimerResolution() } -void xmrig::Platform::setProcessPriority(int priority) -{ -} - - void xmrig::Platform::setThreadPriority(int priority) { if (priority == -1) { diff --git a/src/base/kernel/Platform_unix.cpp b/src/base/kernel/Platform_unix.cpp index bbba39f..b6ca17e 100644 --- a/src/base/kernel/Platform_unix.cpp +++ b/src/base/kernel/Platform_unix.cpp @@ -111,11 +111,6 @@ void xmrig::Platform::restoreTimerResolution() } -void xmrig::Platform::setProcessPriority(int priority) -{ -} - - void xmrig::Platform::setThreadPriority(int priority) { if (priority == -1) { diff --git a/src/base/kernel/Platform_win.cpp b/src/base/kernel/Platform_win.cpp index 064c835..ad93cb6 100644 --- a/src/base/kernel/Platform_win.cpp +++ b/src/base/kernel/Platform_win.cpp @@ -131,43 +131,6 @@ void xmrig::Platform::restoreTimerResolution() } -void xmrig::Platform::setProcessPriority(int priority) -{ - if (priority == -1) { - return; - } - - DWORD prio = IDLE_PRIORITY_CLASS; - switch (priority) - { - case 1: - prio = BELOW_NORMAL_PRIORITY_CLASS; - break; - - case 2: - prio = NORMAL_PRIORITY_CLASS; - break; - - case 3: - prio = ABOVE_NORMAL_PRIORITY_CLASS; - break; - - case 4: - prio = HIGH_PRIORITY_CLASS; - break; - - case 5: - prio = REALTIME_PRIORITY_CLASS; - break; - - default: - break; - } - - SetPriorityClass(GetCurrentProcess(), prio); -} - - void xmrig::Platform::setThreadPriority(int priority) { if (priority == -1) { diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index 5044545..fe1a24b 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -90,8 +90,11 @@ public: RandomXInitKey = 1022, RandomXNumaKey = 1023, RandomXModeKey = 1029, + RandomX1GbPagesKey = 1031, + RandomXWrmsrKey = 1032, CPUMaxThreadsKey = 1026, MemoryPoolKey = 1027, + YieldKey = 1030, // xmrig amd OclPlatformKey = 1400, diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 9729f3f..a995bef 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -79,7 +79,8 @@ static const char *states[] = { xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : BaseClient(id, listener), - m_agent(agent) + m_agent(agent), + m_sendBuf(1024) { m_key = m_storage.add(this); m_dns = new Dns(this); @@ -158,13 +159,18 @@ int64_t xmrig::Client::send(const rapidjson::Value &obj) 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)); + if (size > kMaxSendBufferSize) { + LOG_ERR("[%s] send failed: \"max send buffer size exceeded: %zu\"", url(), size); close(); + return -1; } - memcpy(m_sendBuf, buffer.GetString(), size); + if (size > (m_sendBuf.size() - 2)) { + m_sendBuf.resize(((size + 1) / 1024 + 1) * 1024); + } + + memcpy(m_sendBuf.data(), buffer.GetString(), size); m_sendBuf[size] = '\n'; m_sendBuf[size + 1] = '\0'; @@ -186,8 +192,8 @@ int64_t xmrig::Client::submit(const JobResult &result) const char *nonce = result.nonce; const char *data = result.result; # else - char *nonce = m_sendBuf; - char *data = m_sendBuf + 16; + char *nonce = m_sendBuf.data(); + char *data = m_sendBuf.data() + 16; Buffer::toHex(reinterpret_cast(&result.nonce), 4, nonce); nonce[8] = '\0'; @@ -338,6 +344,10 @@ bool xmrig::Client::isCriticalError(const char *message) return true; } + if (strncasecmp(message, "Invalid job id", 14) == 0) { + return true; + } + return false; } @@ -525,11 +535,11 @@ int xmrig::Client::resolve(const String &host) int64_t xmrig::Client::send(size_t size) { - LOG_DEBUG("[%s] send (%d bytes): \"%.*s\"", url(), size, static_cast(size) - 1, m_sendBuf); + LOG_DEBUG("[%s] send (%d bytes): \"%.*s\"", url(), size, static_cast(size) - 1, m_sendBuf.data()); # ifdef XMRIG_FEATURE_TLS if (isTLS()) { - if (!m_tls->send(m_sendBuf, size)) { + if (!m_tls->send(m_sendBuf.data(), size)) { return -1; } } @@ -541,7 +551,7 @@ int64_t xmrig::Client::send(size_t size) return -1; } - uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size); + uv_buf_t buf = uv_buf_init(m_sendBuf.data(), (unsigned int) size); if (uv_try_write(m_stream, &buf, 1) < 0) { close(); @@ -558,7 +568,7 @@ void xmrig::Client::connect(sockaddr *addr) { setState(ConnectingState); - uv_connect_t *req = new uv_connect_t; + auto req = new uv_connect_t; req->data = m_storage.ptr(m_key); m_socket = new uv_tcp_t; @@ -791,7 +801,7 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co void xmrig::Client::ping() { - send(snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId.data())); + send(snprintf(m_sendBuf.data(), m_sendBuf.size(), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId.data())); m_keepAlive = 0; } @@ -799,7 +809,7 @@ void xmrig::Client::ping() void xmrig::Client::read(ssize_t nread) { - const size_t size = static_cast(nread); + const auto size = static_cast(nread); if (nread > 0 && size > m_recvBuf.available()) { nread = UV_ENOBUFS; @@ -859,7 +869,7 @@ void xmrig::Client::reconnect() void xmrig::Client::setState(SocketState state) { - LOG_DEBUG("[%s] state: \"%s\"", url(), states[state]); + LOG_DEBUG("[%s] state: \"%s\" -> \"%s\"", url(), states[m_state], states[state]); if (m_state == state) { return; @@ -956,6 +966,12 @@ void xmrig::Client::onConnect(uv_connect_t *req, int status) return; } + if (client->state() == ConnectedState) { + LOG_ERR("[%s] already connected"); + + return; + } + client->m_stream = static_cast(req->handle); client->m_stream->data = req->data; client->setState(ConnectedState); diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index da42348..1949e61 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -60,14 +60,10 @@ 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; - -# ifdef XMRIG_FEATURE_TLS - constexpr static size_t kInputBufferSize = 1024 * 16; -# else - constexpr static size_t kInputBufferSize = 1024 * 2; -# endif + constexpr static uint64_t kConnectTimeout = 20 * 1000; + constexpr static uint64_t kResponseTimeout = 20 * 1000; + constexpr static size_t kInputBufferSize = 1024 * 16; + constexpr static size_t kMaxSendBufferSize = 1024 * 16; Client(int id, const char *agent, IClientListener *listener); ~Client() override; @@ -128,11 +124,11 @@ private: static inline Client *getClient(void *data) { return m_storage.get(data); } - char m_sendBuf[2048] = { 0 }; const char *m_agent; Dns *m_dns; RecvBuf m_recvBuf; std::bitset m_extensions; + std::vector m_sendBuf; String m_rpcId; Tls *m_tls = nullptr; uint64_t m_expire = 0; diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 9e1f3bc..ed369a1 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -99,7 +99,7 @@ public: # endif static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast(blob + 39); } - static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; } + static inline uint64_t toDiff(uint64_t target) { return target ? (0xFFFFFFFFFFFFFFFFULL / target) : 0; } inline bool operator!=(const Job &other) const { return !isEqual(other); } inline bool operator==(const Job &other) const { return isEqual(other); } diff --git a/src/crypto/common/Algorithm.cpp b/src/crypto/common/Algorithm.cpp index bf04911..99883da 100644 --- a/src/crypto/common/Algorithm.cpp +++ b/src/crypto/common/Algorithm.cpp @@ -112,6 +112,8 @@ static AlgoName const algorithm_names[] = { { "RandomXL", nullptr, Algorithm::RX_LOKI }, { "randomx/arq", "rx/arq", Algorithm::RX_ARQ }, { "RandomARQ", nullptr, Algorithm::RX_ARQ }, + { "randomx/sfx", "rx/sfx", Algorithm::RX_SFX }, + { "RandomSFX", nullptr, Algorithm::RX_SFX }, # endif # ifdef XMRIG_ALGO_ARGON2 { "argon2/chukwa", nullptr, Algorithm::AR2_CHUKWA }, @@ -138,6 +140,7 @@ size_t xmrig::Algorithm::l2() const switch (m_id) { case RX_0: case RX_LOKI: + case RX_SFX: return 0x40000; case RX_WOW: @@ -157,7 +160,9 @@ size_t xmrig::Algorithm::l2() const size_t xmrig::Algorithm::l3() const { +# if defined(XMRIG_ALGO_RANDOMX) || defined(XMRIG_ALGO_ARGON2) constexpr size_t oneMiB = 0x100000; +# endif const Family f = family(); assert(f != UNKNOWN); @@ -171,6 +176,7 @@ size_t xmrig::Algorithm::l3() const switch (m_id) { case RX_0: case RX_LOKI: + case RX_SFX: return oneMiB * 2; case RX_WOW: @@ -270,6 +276,7 @@ xmrig::Algorithm::Family xmrig::Algorithm::family(Id id) case RX_WOW: case RX_LOKI: case RX_ARQ: + case RX_SFX: return RANDOM_X; # endif diff --git a/src/crypto/common/Algorithm.h b/src/crypto/common/Algorithm.h index 0c6f264..bfdcea5 100644 --- a/src/crypto/common/Algorithm.h +++ b/src/crypto/common/Algorithm.h @@ -67,6 +67,7 @@ public: RX_WOW, // "rx/wow" RandomWOW (Wownero). RX_LOKI, // "rx/loki" RandomXL (Loki). RX_ARQ, // "rx/arq" RandomARQ (Arqma). + RX_SFX, // "rx/sfx" RandomSFX (Safex Cash). AR2_CHUKWA, // "argon2/chukwa" Argon2id (Chukwa). AR2_WRKZ, // "argon2/wrkz" Argon2id (WRKZ) MAX