diff --git a/src/api/NetworkState.h b/src/api/NetworkState.h index c45761fb..f777f984 100644 --- a/src/api/NetworkState.h +++ b/src/api/NetworkState.h @@ -50,7 +50,7 @@ class NetworkState char pool[256]; std::array topDiff { { } }; - uint32_t diff; + uint64_t diff; uint64_t accepted; uint64_t failures; uint64_t rejected; diff --git a/src/base/net/Pool.cpp b/src/base/net/Pool.cpp index 9d4f2bde..d46eaf57 100644 --- a/src/base/net/Pool.cpp +++ b/src/base/net/Pool.cpp @@ -6,6 +6,7 @@ * 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 @@ -65,6 +66,7 @@ xmrig::Pool::Pool() : m_enabled(true), m_nicehash(false), m_tls(false), + m_daemon(false), m_keepAlive(0), m_port(kDefaultPort) { @@ -86,6 +88,7 @@ xmrig::Pool::Pool(const char *url) : m_enabled(true), m_nicehash(false), m_tls(false), + m_daemon(false), m_keepAlive(0), m_port(kDefaultPort) { @@ -135,6 +138,7 @@ xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char m_enabled(true), m_nicehash(nicehash), m_tls(tls), + m_daemon(false), m_keepAlive(keepAlive), m_host(host), m_password(password), @@ -210,17 +214,24 @@ bool xmrig::Pool::parse(const char *url) const char *base = url; if (p) { - if (strncasecmp(url, "stratum+tcp://", 14) == 0) { - m_tls = false; + if (strncasecmp(url, "stratum+", 8) == 0) { + if (p-url != 11) + return false; + } else if (strncasecmp(url, "daemon+",7) == 0) { + if (p-url != 10) + return false; + m_daemon = true; } - else if (strncasecmp(url, "stratum+ssl://", 14) == 0) { + if (strncasecmp(p-3, "tcp:", 4) == 0) { + m_tls = false; + } else if (strncasecmp(p-3, "ssl:", 4) == 0) { m_tls = true; } else { return false; } - base = url + 14; + base = p+3; } if (!strlen(base) || *base == '/') { diff --git a/src/base/net/Pool.h b/src/base/net/Pool.h index a16cc15b..96c13ca7 100644 --- a/src/base/net/Pool.h +++ b/src/base/net/Pool.h @@ -6,6 +6,7 @@ * 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 @@ -60,6 +61,7 @@ class Pool inline bool isNicehash() const { return m_nicehash; } inline bool isTLS() const { return m_tls; } inline bool isValid() const { return !m_host.isNull() && m_port > 0; } + inline bool isDaemon() const { return m_daemon; } inline const char *fingerprint() const { return m_fingerprint.data(); } inline const char *host() const { return m_host.data(); } inline const char *password() const { return !m_password.isNull() ? m_password.data() : kDefaultPassword; } @@ -107,6 +109,7 @@ class Pool bool m_enabled; bool m_nicehash; bool m_tls; + bool m_daemon; int m_keepAlive; String m_fingerprint; String m_host; diff --git a/src/common/net/Client.cpp b/src/common/net/Client.cpp index 7cd09d46..495cf1b3 100644 --- a/src/common/net/Client.cpp +++ b/src/common/net/Client.cpp @@ -6,6 +6,7 @@ * 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 @@ -88,6 +89,7 @@ xmrig::Client::Client(int id, const char *agent, IClientListener *listener) : m_expire(0), m_jobs(0), m_keepAlive(0), + m_daemonPoll(0), m_key(0), m_stream(nullptr), m_socket(nullptr) @@ -160,6 +162,7 @@ void xmrig::Client::setPool(const Pool &pool) } m_pool = pool; + m_daemon = pool.isDaemon(); } @@ -173,6 +176,12 @@ void xmrig::Client::tick(uint64_t now) else if (m_keepAlive && now > m_keepAlive) { ping(); } + if (m_daemonPoll && now > m_daemonPoll) { + send((char *)"GET /getheight HTTP/1.0\r\n\r\n", sizeof("GET /getheight HTTP/1.0\r\n\r\n")-1); + if (m_daemonInterval > 1) + m_daemonInterval >>= 1; + m_daemonPoll = uv_now(uv_default_loop()) + (m_daemonInterval * 1000); + } } if (m_expire && now > m_expire && m_state == ConnectingState) { @@ -223,6 +232,39 @@ int64_t xmrig::Client::submit(const JobResult &result) } # endif + if (m_daemon) { + size_t seqlen, datalen, datalenlen, bufsiz; + char cseq[33], cdata[33], *buf, *nonce; + int64_t rc, sequence; + + if (!m_job.isValid()) + return -1; + + std::string blob = m_job.daemonBlob(); + sequence = m_sequence; + m_job.reset(); + + seqlen = snprintf(cseq, sizeof(cseq), "%" PRId64, sequence); + datalen = blob.size() + sizeof("{\"id\": , \"method\": \"submitblock\", \"params\": [\"\"]}") + seqlen; + datalenlen = snprintf(cdata, sizeof(cdata), "%zd", datalen); + bufsiz = datalen+datalenlen+sizeof("POST /json_rpc HTTP/1.0\r\nContent-Length:\r\n\r\n"); + buf = (char *)malloc(bufsiz); + if (buf == NULL) + return -1; + seqlen = sprintf(buf, "POST /json_rpc HTTP/1.0\r\nContent-Length: %zd\r\n\r\n" + "{\"id\": %zd, \"method\": \"submitblock\", \"params\": [\"%s\"]}", datalen, sequence, blob.c_str()); + nonce = buf + seqlen - blob.size() - 3 + 78; + Job::toHex(reinterpret_cast(&result.nonce), 4, nonce); +# ifdef XMRIG_PROXY_PROJECT + m_results[sequence] = SubmitResult(sequence, result.diff, result.actualDiff(), result.id); +# else + m_results[sequence] = SubmitResult(sequence, result.diff, result.actualDiff()); +# endif + rc = send(buf, bufsiz); + free(buf); + return rc; + } + using namespace rapidjson; # ifdef XMRIG_PROXY_PROJECT @@ -329,33 +371,60 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) Job job(m_id, m_nicehash, m_pool.algorithm(), m_rpcId); - if (!job.setId(params["job_id"].GetString())) { - *code = 3; - return false; - } - - if (!job.setBlob(params["blob"].GetString())) { - *code = 4; - return false; - } + if (m_daemon) { + if (!job.setBlob(params["blockhashing_blob"].GetString())) { + *code = 4; + return false; + } + if (!job.setDiff(params["difficulty"].GetUint64())) { + *code = 5; + return false; + } + const char *bstr = params["blocktemplate_blob"].GetString(); + size_t blen = strlen(bstr); + if (!job.setDaemonBlob(bstr)) { + *code = 4; + return false; + } + /* faking a unique job ID, using last 32 chars of block template blob */ + if (!job.setId(bstr+blen-32)) { + *code = 3; + return false; + } + if (params.HasMember("prev_hash")) { + strncpy(m_prevHash, params["prev_hash"].GetString(), 64); + m_prevHash[64] = '\0'; + } - if (!job.setTarget(params["target"].GetString())) { - *code = 5; - return false; - } + } else { + if (!job.setId(params["job_id"].GetString())) { + *code = 3; + return false; + } - if (params.HasMember("algo")) { - job.setAlgorithm(params["algo"].GetString()); - } + if (!job.setBlob(params["blob"].GetString())) { + *code = 4; + return false; + } - if (params.HasMember("variant")) { - const rapidjson::Value &variant = params["variant"]; + if (!job.setTarget(params["target"].GetString())) { + *code = 5; + return false; + } - if (variant.IsInt()) { - job.setVariant(variant.GetInt()); + if (params.HasMember("algo")) { + job.setAlgorithm(params["algo"].GetString()); } - else if (variant.IsString()){ - job.setVariant(variant.GetString()); + + if (params.HasMember("variant")) { + const rapidjson::Value &variant = params["variant"]; + + if (variant.IsInt()) { + job.setVariant(variant.GetInt()); + } + else if (variant.IsString()){ + job.setVariant(variant.GetString()); + } } } @@ -523,11 +592,15 @@ int64_t xmrig::Client::send(const rapidjson::Document &doc) int64_t xmrig::Client::send(size_t size) { - LOG_DEBUG("[%s] send (%d bytes): \"%s\"", m_pool.url(), size, m_sendBuf); + return send(m_sendBuf, size); +} +int64_t xmrig::Client::send(char *cbuf, size_t size) +{ + LOG_DEBUG("[%s] send (%d bytes): \"%s\"", m_pool.url(), size, cbuf); # ifndef XMRIG_NO_TLS if (isTLS()) { - if (!m_tls->send(m_sendBuf, size)) { + if (!m_tls->send(cbuf, size)) { return -1; } } @@ -539,7 +612,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(cbuf, (unsigned int) size); if (uv_try_write(m_stream, &buf, 1) < 0) { close(); @@ -614,38 +687,48 @@ void xmrig::Client::login() using namespace rapidjson; m_results.clear(); - Document doc(kObjectType); - auto &allocator = doc.GetAllocator(); - - doc.AddMember("id", 1, allocator); - doc.AddMember("jsonrpc", "2.0", allocator); - doc.AddMember("method", "login", allocator); - - Value params(kObjectType); - params.AddMember("login", StringRef(m_pool.user()), allocator); - params.AddMember("pass", StringRef(m_pool.password()), allocator); - params.AddMember("agent", StringRef(m_agent), allocator); - - if (m_pool.rigId()) { - params.AddMember("rigid", StringRef(m_pool.rigId()), allocator); - } + if (m_daemon) { + char cseq[33]; + int clen = snprintf(cseq, sizeof(cseq), "%" PRId64, m_sequence); + send(snprintf(m_sendBuf, sizeof(m_sendBuf), "POST /json_rpc HTTP/1.0\r\nContent-Length: %zd\r\n\r\n" + "{\"id\": %s, \"method\": \"getblocktemplate\", \"params\": {\"reserve_size\": 8, \"wallet_address\": " + "\"%s\"}}", 91+clen+strlen(m_pool.user()), cseq, m_pool.user())); + m_daemonInterval = 32; + + } else { + Document doc(kObjectType); + auto &allocator = doc.GetAllocator(); + Value params(kObjectType); + + doc.AddMember("id", 1, allocator); + doc.AddMember("jsonrpc", "2.0", allocator); + doc.AddMember("method", "login", allocator); + + params.AddMember("login", StringRef(m_pool.user()), allocator); + params.AddMember("pass", StringRef(m_pool.password()), allocator); + params.AddMember("agent", StringRef(m_agent), allocator); + + if (m_pool.rigId()) { + params.AddMember("rigid", StringRef(m_pool.rigId()), allocator); + } # ifdef XMRIG_PROXY_PROJECT - if (m_pool.algorithm().variant() != xmrig::VARIANT_AUTO) + if (m_pool.algorithm().variant() != xmrig::VARIANT_AUTO) # endif - { - Value algo(kArrayType); + { + Value algo(kArrayType); - for (const auto &a : m_pool.algorithms()) { - algo.PushBack(StringRef(a.shortName()), allocator); - } + for (const auto &a : m_pool.algorithms()) { + algo.PushBack(StringRef(a.shortName()), allocator); + } - params.AddMember("algo", algo, allocator); - } + params.AddMember("algo", algo, allocator); + } - doc.AddMember("params", params, allocator); + doc.AddMember("params", params, allocator); - send(doc); + send(doc); + } } @@ -697,6 +780,22 @@ void xmrig::Client::parse(char *line, size_t len) return; } + if (m_daemon) { + /* height check */ + if (doc.HasMember("height")) { + const char *hash = NULL; + uint64_t height = doc["height"].GetUint64(); + if (doc.HasMember("hash")) + hash = doc["hash"].GetString(); + if (height != m_job.height() || + (hash != NULL && strcmp(hash, m_prevHash))) { + /* chain has changed, get a new job */ + login(); + } + return; + } + } + const rapidjson::Value &id = doc["id"]; if (id.IsInt64()) { parseResponse(id.GetInt64(), doc["result"], doc["error"]); @@ -786,9 +885,25 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co return; } + int code = -1; + if (m_daemon) { + if (result.HasMember("difficulty")) { + /* new job */ + if (!parseJob(result, &code)) + goto loginFail; + if (id == 1) { + m_failures = 0; + m_listener->onLoginSuccess(this); + } + m_listener->onJobReceived(this, m_job); + m_daemonPoll = uv_now(uv_default_loop()) + (m_daemonInterval * 1000); + return; + } + } + if (id == 1) { - int code = -1; if (!parseLogin(result, &code)) { +loginFail: if (!isQuiet()) { LOG_ERR("[%s] login error code: %d", m_pool.url(), code); } @@ -808,6 +923,8 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co it->second.done(); m_listener->onResultAccepted(this, it->second, nullptr); m_results.erase(it); + if (m_daemon) + login(); } } @@ -824,13 +941,38 @@ void xmrig::Client::read() char* start = m_recvBuf.base; size_t remaining = m_recvBufPos; - while ((end = static_cast(memchr(start, '\n', remaining))) != nullptr) { - end++; - size_t len = end - start; - parse(start, len); + if (m_daemon) { + char *l, *crlf; + int hlen, rlen; - remaining -= len; - start = end; + start[remaining] = '\0'; + l = strstr(start, "Content-Length: "); + if (!l) + return; + crlf = strstr(l, "\r\n\r\n"); + if (!crlf) + return; + hlen = crlf - start + 4; + if (sscanf(l + sizeof("Content-Length:"), "%d", &rlen) != 1) { + /* fail */ + m_recvBufPos = 0; + return; + } + /* message not yet complete */ + if (remaining-hlen < (unsigned)rlen) + return; + parse(crlf+4, rlen+1); + start = crlf+4 + rlen; + remaining -= hlen + rlen; + } else { + while ((end = static_cast(memchr(start, '\n', remaining))) != nullptr) { + end++; + size_t len = end - start; + parse(start, len); + + remaining -= len; + start = end; + } } if (remaining == 0) { diff --git a/src/common/net/Client.h b/src/common/net/Client.h index 9314739a..2cf1e439 100644 --- a/src/common/net/Client.h +++ b/src/common/net/Client.h @@ -6,6 +6,7 @@ * 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 @@ -83,6 +84,7 @@ class Client void tick(uint64_t now); inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; } + inline const char *mode() const { return m_daemon ? "daemon" : "pool"; } inline const char *host() const { return m_pool.host(); } inline const char *ip() const { return m_ip; } inline const Job &job() const { return m_job; } @@ -113,6 +115,7 @@ class Client int resolve(const char *host); int64_t send(const rapidjson::Document &doc); int64_t send(size_t size); + int64_t send(char *buf, size_t size); void connect(const std::vector &ipv4, const std::vector &ipv6); void connect(sockaddr *addr); void handshake(); @@ -142,15 +145,18 @@ class Client bool m_ipv6; bool m_nicehash; bool m_quiet; + bool m_daemon; char m_buf[kInputBufferSize]; char m_ip[46]; char m_sendBuf[2048]; + char m_prevHash[65]; const char *m_agent; IClientListener *m_listener; int m_extensions; int m_id; int m_retries; int m_retryPause; + int m_daemonInterval; int64_t m_failures; Job m_job; Pool m_pool; @@ -161,6 +167,7 @@ class Client uint64_t m_expire; uint64_t m_jobs; uint64_t m_keepAlive; + uint64_t m_daemonPoll; uintptr_t m_key; uv_buf_t m_recvBuf; uv_getaddrinfo_t m_resolver; diff --git a/src/common/net/Job.cpp b/src/common/net/Job.cpp index 851507ad..d56fd40d 100644 --- a/src/common/net/Job.cpp +++ b/src/common/net/Job.cpp @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2018 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -99,6 +100,15 @@ bool xmrig::Job::isEqual(const Job &other) const } +bool xmrig::Job::setDaemonBlob(const char *blob) +{ + if (!blob) { + return false; + } + m_daemonBlob = blob; + return true; +} + bool xmrig::Job::setBlob(const char *blob) { if (!blob) { @@ -154,6 +164,14 @@ bool xmrig::Job::setBlob(const char *blob) } +bool xmrig::Job::setDiff(uint64_t diff) +{ + m_diff = diff; + m_target = toDiff(diff); + + return true; +} + bool xmrig::Job::setTarget(const char *target) { if (!target) { diff --git a/src/common/net/Job.h b/src/common/net/Job.h index 49ddc7da..9089e71c 100644 --- a/src/common/net/Job.h +++ b/src/common/net/Job.h @@ -7,6 +7,7 @@ * Copyright 2017-2018 XMR-Stak , * Copyright 2018 Lee Clagett * Copyright 2018-2019 SChernykh + * Copyright 2019 Howard Chu * Copyright 2016-2019 XMRig , * * This program is free software: you can redistribute it and/or modify @@ -30,6 +31,7 @@ #include #include +#include #include "common/crypto/Algorithm.h" #include "common/net/Id.h" @@ -52,6 +54,8 @@ class Job bool isEqual(const Job &other) const; bool setBlob(const char *blob); bool setTarget(const char *target); + bool setDiff(uint64_t diff); + bool setDaemonBlob(const char *blob); void setAlgorithm(const char *algo); void setHeight(uint64_t height); @@ -60,6 +64,7 @@ class Job inline bool setId(const char *id) { return m_id.setId(id); } inline const uint32_t *nonce() const { return reinterpret_cast(m_blob + 39); } inline const uint8_t *blob() const { return m_blob; } + inline std::string& daemonBlob() { return m_daemonBlob; } inline const Algorithm &algorithm() const { return m_algorithm; } inline const Id &clientId() const { return m_clientId; } inline const Id &id() const { return m_id; } @@ -67,7 +72,7 @@ class Job inline int threadId() const { return m_threadId; } inline size_t size() const { return m_size; } inline uint32_t *nonce() { return reinterpret_cast(m_blob + 39); } - inline uint32_t diff() const { return static_cast(m_diff); } + inline uint64_t diff() const { return m_diff; } inline uint64_t target() const { return m_target; } inline uint64_t height() const { return m_height; } inline void reset() { m_size = 0; m_diff = 0; } @@ -114,6 +119,7 @@ class Job char m_rawBlob[kMaxBlobSize * 2 + 8]; char m_rawTarget[24]; # endif + std::string m_daemonBlob; }; diff --git a/src/common/net/SubmitResult.cpp b/src/common/net/SubmitResult.cpp index d14bbb40..7171cd7e 100644 --- a/src/common/net/SubmitResult.cpp +++ b/src/common/net/SubmitResult.cpp @@ -29,7 +29,7 @@ #include "common/net/SubmitResult.h" -xmrig::SubmitResult::SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId) : +xmrig::SubmitResult::SubmitResult(int64_t seq, uint64_t diff, uint64_t actualDiff, int64_t reqId) : reqId(reqId), seq(seq), diff(diff), diff --git a/src/common/net/SubmitResult.h b/src/common/net/SubmitResult.h index db97ac38..a992d302 100644 --- a/src/common/net/SubmitResult.h +++ b/src/common/net/SubmitResult.h @@ -36,13 +36,13 @@ class SubmitResult { public: inline SubmitResult() : reqId(0), seq(0), diff(0), actualDiff(0), elapsed(0), start(0) {} - SubmitResult(int64_t seq, uint32_t diff, uint64_t actualDiff, int64_t reqId = 0); + SubmitResult(int64_t seq, uint64_t diff, uint64_t actualDiff, int64_t reqId = 0); void done(); int64_t reqId; int64_t seq; - uint32_t diff; + uint64_t diff; uint64_t actualDiff; uint64_t elapsed; diff --git a/src/net/JobResult.h b/src/net/JobResult.h index 5ab4d294..b2d16c2a 100644 --- a/src/net/JobResult.h +++ b/src/net/JobResult.h @@ -40,20 +40,20 @@ namespace xmrig { class JobResult { public: - inline JobResult() : poolId(0), diff(0), nonce(0) {} - inline JobResult(int poolId, const Id &jobId, const Id &clientId, uint32_t nonce, const uint8_t *result, uint32_t diff, const Algorithm &algorithm) : + inline JobResult() : poolId(0), nonce(0), diff(0) {} + inline JobResult(int poolId, const Id &jobId, const Id &clientId, uint32_t nonce, const uint8_t *result, uint64_t diff, const Algorithm &algorithm) : algorithm(algorithm), clientId(clientId), jobId(jobId), poolId(poolId), - diff(diff), - nonce(nonce) + nonce(nonce), + diff(diff) { memcpy(this->result, result, sizeof(this->result)); } - inline JobResult(const Job &job) : poolId(0), diff(0), nonce(0) + inline JobResult(const Job &job) : poolId(0), nonce(0), diff(0) { jobId = job.id(); clientId = job.clientId(); @@ -74,8 +74,8 @@ class JobResult Id clientId; Id jobId; int poolId; - uint32_t diff; uint32_t nonce; + uint64_t diff; uint8_t result[32]; }; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 34714c8a..f3f7affb 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -6,6 +6,7 @@ * 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 @@ -94,9 +95,9 @@ void xmrig::Network::onActive(IStrategy *strategy, Client *client) m_state.setPool(client->host(), client->port(), client->ip()); const char *tlsVersion = client->tlsVersion(); - LOG_INFO(isColors() ? WHITE_BOLD("use pool ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " \x1B[1;30m%s " - : "use pool %s:%d %s %s", - client->host(), client->port(), tlsVersion ? tlsVersion : "", client->ip()); + LOG_INFO(isColors() ? WHITE_BOLD("use %s ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " \x1B[1;30m%s " + : "use %s %s:%d %s %s", + client->mode(), client->host(), client->port(), tlsVersion ? tlsVersion : "", client->ip()); const char *fingerprint = client->tlsFingerprint(); if (fingerprint != nullptr) { @@ -162,13 +163,13 @@ void xmrig::Network::onResultAccepted(IStrategy *, Client *, const SubmitResult m_state.add(result, error); if (error) { - LOG_INFO(isColors() ? "\x1B[1;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[1;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[1;30m(%" PRIu64 " ms)" - : "rejected (%" PRId64 "/%" PRId64 ") diff %u \"%s\" (%" PRIu64 " ms)", + LOG_INFO(isColors() ? "\x1B[1;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[1;37m%" PRIu64 "\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[1;30m(%" PRIu64 " ms)" + : "rejected (%" PRId64 "/%" PRId64 ") diff %" PRIu64 " \"%s\" (%" PRIu64 " ms)", m_state.accepted, m_state.rejected, result.diff, error, result.elapsed); } else { - LOG_INFO(isColors() ? "\x1B[1;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[1;37m%u\x1B[0m \x1B[1;30m(%" PRIu64 " ms)" - : "accepted (%" PRId64 "/%" PRId64 ") diff %u (%" PRIu64 " ms)", + LOG_INFO(isColors() ? "\x1B[1;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[1;37m%" PRIu64 "\x1B[0m \x1B[1;30m(%" PRIu64 " ms)" + : "accepted (%" PRId64 "/%" PRId64 ") diff %" PRIu64 " (%" PRIu64 " ms)", m_state.accepted, m_state.rejected, result.diff, result.elapsed); } } @@ -183,13 +184,13 @@ bool xmrig::Network::isColors() const void xmrig::Network::setJob(Client *client, const Job &job, bool donate) { if (job.height()) { - LOG_INFO(isColors() ? MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64) - : "new job from %s:%d diff %d algo %s height %" PRIu64, + LOG_INFO(isColors() ? MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64) + : "new job from %s:%d diff %" PRIu64 " algo %s height %" PRIu64, client->host(), client->port(), job.diff(), job.algorithm().shortName(), job.height()); } else { - LOG_INFO(isColors() ? MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%d") " algo " WHITE_BOLD("%s") - : "new job from %s:%d diff %d algo %s", + LOG_INFO(isColors() ? MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64) " algo " WHITE_BOLD("%s") + : "new job from %s:%d diff %" PRIu64 " algo %s", client->host(), client->port(), job.diff(), job.algorithm().shortName()); }