diff --git a/CHANGELOG.md b/CHANGELOG.md index 9455ddd5..e4a44aff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 1.5.3 +- Fixed Bad/Invalid shares and high share transmit latency +- Fixed hugepages for some older linux versions +- Added force algo variant by xmrig-proxy 2.5.x+ +- Added auto force of nicehash param by xmrig-proxy 2.5.x+ +- Partial rebase of XMRig 2.5.2 # 1.5.2 - Fixed OSX Build - Fixed force PoW algo version diff --git a/src/3rdparty/clib-net/include/net.h b/src/3rdparty/clib-net/include/net.h index 3ed2a9c3..4b061b6c 100644 --- a/src/3rdparty/clib-net/include/net.h +++ b/src/3rdparty/clib-net/include/net.h @@ -153,10 +153,4 @@ net_pause(net_t * net); int net_set_error_cb(net_t * net, void * cb); -/* - * write buffer, and call `net_write_cb`. - */ -void -net_write_cb(uv_write_t *writer, int stat); - #endif /* __NET_H__ */ \ No newline at end of file diff --git a/src/3rdparty/clib-net/src/net.c b/src/3rdparty/clib-net/src/net.c index 69a7f596..02c44366 100644 --- a/src/3rdparty/clib-net/src/net.c +++ b/src/3rdparty/clib-net/src/net.c @@ -53,6 +53,10 @@ net_close(net_t * net, void (*cb)(uv_handle_t*)) { } #endif + if (uv_is_readable((uv_stream_t*)net->handle) == 1) { + uv_read_stop((uv_stream_t*)net->handle); + } + uv_close((uv_handle_t*)net->handle, cb); #ifndef XMRIG_NO_TLS @@ -154,6 +158,12 @@ net_resolve_cb(uv_getaddrinfo_t *rv, int err, net_ai * ai) { * create tcp instance. */ uv_tcp_init(net->loop, net->handle); + uv_tcp_nodelay(net->handle, 1); + +# ifndef WIN32 + uv_tcp_keepalive(net->handle, 1, 60); +# endif + ret = uv_tcp_connect(net->conn, net->handle, (const struct sockaddr*) &dest, net_connect_cb); if (ret != NET_OK) { if (net->error_cb) { @@ -209,19 +219,16 @@ net_connect_cb(uv_connect_t *conn, int err) { * Handle TLS Partial */ if (net->use_ssl == USE_SSL && tls_connect(net->tls) == NET_OK) { - read = 0; do { read = tls_bio_read(net->tls, 0); if (read > 0) { char* buf = (char *) calloc(read, 1); - uv_write_t * req = malloc(sizeof(uv_write_t)); - req->data = net; memset(buf, 0, read); memcpy(buf, net->tls->buf, read); uv_buf_t uvbuf = uv_buf_init(buf, read); - uv_write(req, (uv_stream_t*)net->handle, &uvbuf, 1, net_write_cb); + uv_try_write((uv_stream_t*)net->handle, &uvbuf, 1); free(buf); - } + } } while (read > 0); } #endif @@ -269,12 +276,10 @@ net_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { read = tls_bio_read(net->tls, 0); if (read > 0) { char* buf2 = (char *) calloc(read, 1); - uv_write_t * req = malloc(sizeof(uv_write_t)); - req->data = net; memset(buf2, 0, read); memcpy(buf2, net->tls->buf, read); uv_buf_t uvbuf = uv_buf_init(buf2, read); - uv_write(req, (uv_stream_t*)net->handle, &uvbuf, 1, net_write_cb); + uv_try_write((uv_stream_t*)net->handle, &uvbuf, 1); free(buf2); } } while (read > 0); @@ -311,7 +316,7 @@ net_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { /* * TCP Part, no SSL, just proxy of uv. */ - uv_read_stop(handle); + //uv_read_stop(handle); buf->base[nread] = 0; if (net->read_cb != NULL) { net->read_cb(net, nread, buf->base); @@ -326,9 +331,9 @@ net_write(net_t * net, char * buf) { int net_write2(net_t * net, char * buf, unsigned int len) { - uv_write_t * req; uv_buf_t uvbuf; int read = 0; + int res = NET_OK; switch (net->use_ssl) { case USE_SSL: @@ -337,29 +342,19 @@ net_write2(net_t * net, char * buf, unsigned int len) { do { read = tls_bio_read(net->tls, 0); if (read > 0) { - req = (uv_write_t *) malloc(sizeof(uv_write_t)); - req->data = net; uvbuf = uv_buf_init(net->tls->buf, read); - uv_write(req, (uv_stream_t*)net->handle, - &uvbuf, - 1, - net_write_cb); + res = uv_try_write((uv_stream_t*)net->handle, &uvbuf,1); } } while (read > 0); break; #endif case NOT_SSL: - req = (uv_write_t *) malloc(sizeof(uv_write_t)); - req->data = net; uvbuf = uv_buf_init(buf, len); - uv_write(req, (uv_stream_t*)net->handle, - &uvbuf, - 1, - net_write_cb); + res = uv_try_write((uv_stream_t*)net->handle, &uvbuf, 1); break; } - return NET_OK; + return res; } int @@ -384,9 +379,3 @@ net_set_error_cb(net_t * net, void * cb) { net->error_cb = cb; return NET_OK; } - -void -net_write_cb(uv_write_t *req, int stat) { - net_resume((net_t*)req->data); - free(req); -} diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp index a2d5c911..00dab9b3 100644 --- a/src/crypto/CryptoNight.cpp +++ b/src/crypto/CryptoNight.cpp @@ -122,9 +122,20 @@ void CryptoNight::hash(size_t factor, const uint8_t* input, size_t size, uint8_t bool CryptoNight::selfTest(int algo) { - if (cryptonight_hash_ctx[0] == nullptr || cryptonight_hash_ctx[2] == nullptr || - cryptonight_hash_ctx[2] == nullptr || cryptonight_hash_ctx[3] == nullptr || - cryptonight_hash_ctx[4] == nullptr) { + if (cryptonight_hash_ctx[0] == nullptr +#if MAX_NUM_HASH_BLOCKS > 1 + || cryptonight_hash_ctx[1] == nullptr +#endif +#if MAX_NUM_HASH_BLOCKS > 2 + || cryptonight_hash_ctx[2] == nullptr +#endif +#if MAX_NUM_HASH_BLOCKS > 3 + || cryptonight_hash_ctx[3] == nullptr +#endif +#if MAX_NUM_HASH_BLOCKS > 4 + || cryptonight_hash_ctx[4] == nullptr +#endif + ) { return false; } @@ -138,17 +149,25 @@ bool CryptoNight::selfTest(int algo) cryptonight_hash_ctx[0](test_input, 76, output, ctx); resultV1Pow = resultV1Pow && memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output_light : test_output, 32) == 0; +#if MAX_NUM_HASH_BLOCKS > 1 cryptonight_hash_ctx[1](test_input, 76, output, ctx); resultV1Pow = resultV1Pow && memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output_light : test_output, 64) == 0; +#endif +#if MAX_NUM_HASH_BLOCKS > 2 cryptonight_hash_ctx[2](test_input, 76, output, ctx); resultV1Pow = resultV1Pow && memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output_light : test_output, 96) == 0; +#endif +#if MAX_NUM_HASH_BLOCKS > 3 cryptonight_hash_ctx[3](test_input, 76, output, ctx); resultV1Pow = resultV1Pow && memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output_light : test_output, 128) == 0; +#endif +#if MAX_NUM_HASH_BLOCKS > 4 cryptonight_hash_ctx[4](test_input, 76, output, ctx); resultV1Pow = resultV1Pow && memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output_light : test_output, 160) == 0; +#endif } // monero/aeon v2 pow (monero/aeon blockchain version 7) @@ -157,12 +176,15 @@ bool CryptoNight::selfTest(int algo) cryptonight_hash_ctx[0](test_input_monero_v2_pow_0, sizeof(test_input_monero_v2_pow_0), output, ctx); resultV2Pow = resultV2Pow && memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output_monero_v2_pow_light[0] : test_output_monero_v2_pow[0], 32) == 0; +#if MAX_NUM_HASH_BLOCKS > 1 cryptonight_hash_ctx[1](test_input_monero_v2_pow_1, sizeof(test_input_monero_v2_pow_1), output, ctx); resultV2Pow = resultV2Pow && memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output_monero_v2_pow_light[1] : test_output_monero_v2_pow[1], 32) == 0; +#endif +#if MAX_NUM_HASH_BLOCKS > 2 cryptonight_hash_ctx[2](test_input_monero_v2_pow_2, sizeof(test_input_monero_v2_pow_2), output, ctx); resultV2Pow = resultV2Pow && memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output_monero_v2_pow_light[2] : test_output_monero_v2_pow[2], 32) == 0; - //TODO test multihashs +#endif } _mm_free(ctx->memory); diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index c14c0172..2e954a28 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -360,11 +360,12 @@ public: for (size_t i = 0; i < ITERATIONS; i++) { for (size_t hashBlock = 0; hashBlock < NUM_HASH_BLOCKS; ++hashBlock) { - __m128i cx = _mm_load_si128((__m128i*) &l[hashBlock][idx[hashBlock] & MASK]); + __m128i cx; if (SOFT_AES) { - cx = soft_aesenc(cx, _mm_set_epi64x(ah[hashBlock], al[hashBlock])); + cx = soft_aesenc((uint32_t*) &l[hashBlock][idx[hashBlock] & MASK], _mm_set_epi64x(ah[hashBlock], al[hashBlock])); } else { + cx = _mm_load_si128((__m128i*) &l[hashBlock][idx[hashBlock] & MASK]); cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah[hashBlock], al[hashBlock])); } diff --git a/src/net/Client.cpp b/src/net/Client.cpp index e73b474f..daf98f09 100644 --- a/src/net/Client.cpp +++ b/src/net/Client.cpp @@ -55,13 +55,15 @@ int64_t Client::m_sequence = 1; Client::Client(int id, const char *agent, IClientListener *listener) : m_quiet(false), + m_nicehash(false), m_agent(agent), m_listener(listener), m_id(id), m_retryPause(5000), m_failures(0), m_recvBufPos(0), - m_expire(0) + m_expire(0), + m_jobs(0) { m_recvBuf.base = m_buf; m_recvBuf.len = sizeof(m_buf); @@ -95,6 +97,8 @@ void Client::connect(const Url *url) void Client::disconnect() { + LOG_DEBUG("Client::disconnect"); + # ifndef XMRIG_PROXY_PROJECT uv_timer_stop(&m_keepAliveTimer); # endif @@ -123,10 +127,11 @@ void Client::tick(uint64_t now) } if (m_net) { - LOG_DEBUG_ERR("[%s:%u] timeout", m_url.host(), m_url.port()); - reconnect(); + LOG_WARN("[%s:%u] timeout", m_url.host(), m_url.port()); + close(); } else { + LOG_DEBUG("Client::tick -> connect"); connect(); } } @@ -185,7 +190,7 @@ bool Client::parseJob(const rapidjson::Value ¶ms, int *code) return false; } - Job job(m_id, m_url.isNicehash()); + Job job(m_id, m_nicehash); if (!job.setId(params["job_id"].GetString())) { *code = 3; return false; @@ -221,17 +226,22 @@ bool Client::parseJob(const rapidjson::Value ¶ms, int *code) } } - if (m_job == job) { - if (!m_quiet) { - LOG_WARN("[%s:%u] duplicate job received, reconnect", m_url.host(), m_url.port()); - } + if (m_job != job) { + m_jobs++; + m_job = std::move(job); + return true; + } - close(); + if (m_jobs == 0) { // https://github.com/xmrig/xmrig/issues/459 return false; } - m_job = std::move(job); - return true; + if (!m_quiet) { + LOG_WARN("[%s:%u] duplicate job received, reconnect", m_url.host(), m_url.port()); + } + + close(); + return false; } @@ -243,14 +253,27 @@ bool Client::parseLogin(const rapidjson::Value &result, int *code) return false; } +# ifndef XMRIG_PROXY_PROJECT + m_nicehash = m_url.isNicehash(); +# endif + + if (result.HasMember("extensions")) { + parseExtensions(result["extensions"]); + } + memset(m_rpcId, 0, sizeof(m_rpcId)); memcpy(m_rpcId, id, strlen(id)); - return parseJob(result["job"], code); + const bool rc = parseJob(result["job"], code); + m_jobs = 0; + + return rc; } int64_t Client::send(size_t size) { + LOG_DEBUG("Client::send"); + LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size, m_sendBuf); if (!m_net) { LOG_DEBUG_ERR("[%s:%u] send failed", m_url.host(), m_url.port()); @@ -269,6 +292,8 @@ int64_t Client::send(size_t size) void Client::close() { + LOG_DEBUG("Client::close"); + if (m_net) { auto client = getClient(m_net->data); @@ -283,6 +308,8 @@ void Client::close() void Client::connect() { + LOG_DEBUG("Client::connect"); + m_net = net_new(const_cast(m_url.host()), m_url.port()); m_net->data = this; m_net->conn_cb = Client::onConnect; @@ -301,6 +328,8 @@ void Client::connect() void Client::onRead(net_t *net, size_t size, char *buf) { + LOG_DEBUG("Client::onRead"); + auto client = getClient(net->data); if (size == 0) { @@ -340,12 +369,15 @@ void Client::onRead(net_t *net, size_t size, char *buf) } void Client::onConnect(net_t *net) { + LOG_DEBUG("Client::onConnect"); auto client = getClient(net->data); client->login(); } void Client::onError(net_t *net, int err, char *errStr) { + LOG_DEBUG("Client::onError"); + if (net) { auto client = getClient(net->data); if (!client->m_quiet) { @@ -358,6 +390,8 @@ void Client::onError(net_t *net, int err, char *errStr) void Client::login() { + LOG_DEBUG("Client::login"); + m_results.clear(); rapidjson::Document doc; @@ -395,6 +429,8 @@ void Client::login() void Client::parse(char *line, size_t len) { + LOG_DEBUG("Client::parse"); + startTimeout(); line[len - 1] = '\0'; @@ -424,6 +460,23 @@ void Client::parse(char *line, size_t len) } +void Client::parseExtensions(const rapidjson::Value &value) +{ + if (!value.IsArray()) { + return; + } + + for (const rapidjson::Value &ext : value.GetArray()) { + if (!ext.IsString()) { + continue; + } + + if (strcmp(ext.GetString(), "nicehash") == 0) { + m_nicehash = true; + } + } +} + void Client::parseNotification(const char *method, const rapidjson::Value ¶ms, const rapidjson::Value &error) { if (error.IsObject()) { @@ -503,12 +556,15 @@ void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rap void Client::ping() { + LOG_DEBUG("Client::ping"); send(snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId)); } void Client::reconnect() { + LOG_DEBUG("Client::reconnect"); + # ifndef XMRIG_PROXY_PROJECT if (m_url.isKeepAlive()) { uv_timer_stop(&m_keepAliveTimer); @@ -516,6 +572,7 @@ void Client::reconnect() { # endif if (m_failures == -1) { + LOG_DEBUG("Client::onConnect -> m_failures == -1"); return m_listener->onClose(this, -1); } @@ -527,6 +584,8 @@ void Client::reconnect() { void Client::startTimeout() { + LOG_DEBUG("Client::startTimeout"); + m_expire = 0; # ifndef XMRIG_PROXY_PROJECT diff --git a/src/net/Client.h b/src/net/Client.h index b2b422f6..36648525 100644 --- a/src/net/Client.h +++ b/src/net/Client.h @@ -86,6 +86,7 @@ private: void close(); void login(); void parse(char *line, size_t len); + void parseExtensions(const rapidjson::Value &value); void parseNotification(const char *method, const rapidjson::Value ¶ms, const rapidjson::Value &error); void parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); void ping(); @@ -99,6 +100,7 @@ private: static inline Client *getClient(void *data) { return static_cast(data); } bool m_quiet; + bool m_nicehash; char m_buf[2048]; char m_rpcId[64]; char m_sendBuf[768]; @@ -112,6 +114,7 @@ private: static int64_t m_sequence; std::map m_results; uint64_t m_expire; + uint64_t m_jobs; Url m_url; uv_buf_t m_recvBuf; diff --git a/src/net/Job.cpp b/src/net/Job.cpp index c3d33739..01d72e8f 100644 --- a/src/net/Job.cpp +++ b/src/net/Job.cpp @@ -61,7 +61,8 @@ Job::Job(int poolId, bool nicehash) : m_threadId(-1), m_size(0), m_diff(0), - m_target(0) + m_target(0), + m_blob() { } @@ -173,3 +174,8 @@ bool Job::operator==(const Job &other) const { return m_id == other.m_id && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0; } + +bool Job::operator!=(const Job &other) const +{ + return m_id != other.m_id || memcmp(m_blob, other.m_blob, sizeof(m_blob)) != 0; +} \ No newline at end of file diff --git a/src/net/Job.h b/src/net/Job.h index 4763a7c2..b7235a86 100644 --- a/src/net/Job.h +++ b/src/net/Job.h @@ -67,9 +67,9 @@ public: static void toHex(const unsigned char* in, unsigned int len, char* out); bool operator==(const Job &other) const; + bool operator!=(const Job &other) const; private: - alignas(16) uint8_t m_blob[84]; // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk. bool m_nicehash; int m_poolId; @@ -79,6 +79,8 @@ private: uint64_t m_diff; uint64_t m_target; + alignas(16) uint8_t m_blob[84]; // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk. + # ifdef XMRIG_PROXY_PROJECT VAR_ALIGN(16, char m_rawBlob[169]); VAR_ALIGN(16, char m_rawTarget[17]); diff --git a/src/net/JobId.h b/src/net/JobId.h index 06189779..abcbbd27 100644 --- a/src/net/JobId.h +++ b/src/net/JobId.h @@ -31,15 +31,15 @@ class JobId { public: - inline JobId() + inline JobId() : + m_data() { - memset(m_data, 0, sizeof(m_data)); } - inline JobId(const char *id, size_t sizeFix = 0) + inline JobId(const char *jobId, size_t sizeFix = 0) { - setId(id, sizeFix); + setId(jobId, sizeFix); } @@ -55,19 +55,27 @@ public: } - inline bool setId(const char *id, size_t sizeFix = 0) + JobId &operator=(const JobId &other) + { + memcpy(m_data, other.m_data, sizeof(m_data)); + + return *this; + } + + + inline bool setId(const char *jobId, size_t sizeFix = 0) { memset(m_data, 0, sizeof(m_data)); - if (!id) { + if (!jobId) { return false; } - const size_t size = strlen(id); + const size_t size = strlen(jobId); if (size >= sizeof(m_data)) { return false; } - memcpy(m_data, id, size - sizeFix); + memcpy(m_data, jobId, size - sizeFix); return true; } diff --git a/src/version.h b/src/version.h index ac26ad30..9bf429a9 100644 --- a/src/version.h +++ b/src/version.h @@ -36,7 +36,7 @@ #define APP_DESC "XMRigCC CPU miner" #define APP_COPYRIGHT "Copyright (C) 2017- BenDr0id" #endif -#define APP_VERSION "1.5.3 (based on XMRig 2.4.5)" +#define APP_VERSION "1.5.3 (based on XMRig 2.5.2)" #define APP_DOMAIN "" #define APP_SITE "https://github.com/Bendr0id/xmrigCC" #define APP_KIND "cpu"