diff --git a/cmake/astrobwt.cmake b/cmake/astrobwt.cmake index f0ebf5306..5b0b76917 100644 --- a/cmake/astrobwt.cmake +++ b/cmake/astrobwt.cmake @@ -3,10 +3,12 @@ if (WITH_ASTROBWT) list(APPEND HEADERS_CRYPTO src/crypto/astrobwt/AstroBWT.h + src/crypto/astrobwt/sort_indices2.h ) list(APPEND SOURCES_CRYPTO src/crypto/astrobwt/AstroBWT.cpp + src/crypto/astrobwt/sort_indices2.cpp ) if (XMRIG_ARM) @@ -21,6 +23,10 @@ if (WITH_ASTROBWT) src/crypto/astrobwt/salsa20_ref/salsa20.c ) else() + if (CMAKE_C_COMPILER_ID MATCHES MSVC) + set_source_files_properties(src/crypto/astrobwt/sort_indices2.cpp PROPERTIES COMPILE_FLAGS "/std:c++20") + endif() + if (CMAKE_SIZEOF_VOID_P EQUAL 8) add_definitions(/DASTROBWT_AVX2) list(APPEND SOURCES_CRYPTO src/crypto/astrobwt/xmm6int/salsa20_xmm6int-avx2.c) diff --git a/src/backend/cpu/CpuConfig_gen.h b/src/backend/cpu/CpuConfig_gen.h index 5ba107380..6698861af 100644 --- a/src/backend/cpu/CpuConfig_gen.h +++ b/src/backend/cpu/CpuConfig_gen.h @@ -157,7 +157,15 @@ size_t inline generate(Threads &threads, uint32_t template<> size_t inline generate(Threads& threads, uint32_t limit) { - return generate(Algorithm::kASTROBWT, threads, Algorithm::ASTROBWT_DERO, limit); + size_t count = 0; + + if (!threads.isExist(Algorithm::ASTROBWT_DERO_2)) { + auto v2 = Cpu::info()->threads(Algorithm::ASTROBWT_DERO_2, limit); + count += threads.move(Algorithm::kASTROBWT_DERO_2, std::move(v2)); + } + + count += generate(Algorithm::kASTROBWT, threads, Algorithm::ASTROBWT_DERO, limit); + return count; } #endif diff --git a/src/backend/cpu/CpuWorker.cpp b/src/backend/cpu/CpuWorker.cpp index 86201e506..4109a6cf2 100644 --- a/src/backend/cpu/CpuWorker.cpp +++ b/src/backend/cpu/CpuWorker.cpp @@ -224,9 +224,8 @@ bool xmrig::CpuWorker::selfTest() # endif # ifdef XMRIG_ALGO_ASTROBWT - if (m_algorithm.family() == Algorithm::ASTROBWT) { - return verify(Algorithm::ASTROBWT_DERO, astrobwt_dero_test_out); - } + if (m_algorithm.id() == Algorithm::ASTROBWT_DERO) return verify(Algorithm::ASTROBWT_DERO, astrobwt_dero_test_out); + if (m_algorithm.id() == Algorithm::ASTROBWT_DERO_2) return verify(Algorithm::ASTROBWT_DERO_2, astrobwt_dero_2_test_out); # endif return false; @@ -320,8 +319,15 @@ void xmrig::CpuWorker::start() # ifdef XMRIG_ALGO_ASTROBWT case Algorithm::ASTROBWT: - if (!astrobwt::astrobwt_dero(m_job.blob(), job.size(), m_ctx[0]->memory, m_hash, m_astrobwtMaxSize, m_astrobwtAVX2)) { - valid = false; + if (job.algorithm().id() == Algorithm::ASTROBWT_DERO) { + if (!astrobwt::astrobwt_dero(m_job.blob(), job.size(), m_ctx[0]->memory, m_hash, m_astrobwtMaxSize, m_astrobwtAVX2)) { + valid = false; + } + } + else { + if (!astrobwt::astrobwt_dero_v2(m_job.blob(), job.size(), m_ctx[0]->memory, m_hash)) { + valid = false; + } } break; # endif diff --git a/src/base/crypto/Algorithm.cpp b/src/base/crypto/Algorithm.cpp index 636a638cd..9dda0cdcf 100644 --- a/src/base/crypto/Algorithm.cpp +++ b/src/base/crypto/Algorithm.cpp @@ -94,6 +94,7 @@ const char *Algorithm::kAR2_WRKZ = "argon2/ninja"; #ifdef XMRIG_ALGO_ASTROBWT const char *Algorithm::kASTROBWT = "astrobwt"; const char *Algorithm::kASTROBWT_DERO = "astrobwt"; +const char *Algorithm::kASTROBWT_DERO_2 = "astrobwt/v2"; #endif #ifdef XMRIG_ALGO_KAWPOW @@ -163,6 +164,7 @@ static const std::map kAlgorithmNames = { # ifdef XMRIG_ALGO_ASTROBWT ALGO_NAME(ASTROBWT_DERO), + ALGO_NAME(ASTROBWT_DERO_2), # endif # ifdef XMRIG_ALGO_KAWPOW @@ -282,6 +284,8 @@ static const std::map kAlgorithmAlias # ifdef XMRIG_ALGO_ASTROBWT ALGO_ALIAS_AUTO(ASTROBWT_DERO), ALGO_ALIAS(ASTROBWT_DERO, "astrobwt/dero"), + ALGO_ALIAS_AUTO(ASTROBWT_DERO_2), ALGO_ALIAS(ASTROBWT_DERO_2, "astrobwt/derov2"), + ALGO_ALIAS_AUTO(ASTROBWT_DERO_2), ALGO_ALIAS(ASTROBWT_DERO_2, "astrobwt/v2"), # endif # ifdef XMRIG_ALGO_KAWPOW @@ -365,7 +369,7 @@ std::vector xmrig::Algorithm::all(const std::function +#endif + + #include #include +#include namespace xmrig { @@ -58,7 +64,9 @@ namespace xmrig { Storage DaemonClient::m_storage; -static const char* kBlocktemplateBlob = "blocktemplate_blob"; +static const char* kBlocktemplateBlob = "blocktemplate_blob"; +static const char* kBlockhashingBlob = "blockhashing_blob"; +static const char* kLastError = "lasterror"; static const char *kGetHeight = "/getheight"; static const char *kGetInfo = "/getinfo"; static const char *kHash = "hash"; @@ -73,6 +81,14 @@ static constexpr size_t kZMQGreetingSize1 = 11; static const char kZMQHandshake[] = "\4\x19\5READY\xbSocket-Type\0\0\0\3SUB"; static const char kZMQSubscribe[] = "\0\x18\1json-minimal-chain_main"; +static const char kWSSLogin[] = "\ +GET /ws/%s HTTP/1.1\r\n\ +Host: %s\r\n\ +Upgrade: websocket\r\n\ +Connection: Upgrade\r\n\ +Sec-WebSocket-Key: %s\r\n\ +Sec-WebSocket-Version: 13\r\n\r\n"; + } // namespace xmrig @@ -89,11 +105,20 @@ xmrig::DaemonClient::~DaemonClient() { delete m_timer; delete m_ZMQSocket; +# ifdef XMRIG_FEATURE_TLS + delete m_wss.m_socket; +# endif } void xmrig::DaemonClient::deleteLater() { +# ifdef XMRIG_FEATURE_TLS + if (m_pool.isWSS()) { + WSSClose(true); + } + else +# endif if (m_pool.zmq_port() >= 0) { ZMQClose(true); } @@ -123,6 +148,12 @@ bool xmrig::DaemonClient::isTLS() const } +bool xmrig::DaemonClient::isWSS() const +{ + return m_pool.isWSS(); +} + + int64_t xmrig::DaemonClient::submit(const JobResult &result) { if (result.jobId != m_currentJobId) { @@ -151,6 +182,17 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result) Cvt::toHex(data + m_job.nonceOffset() * 2, 8, reinterpret_cast(&result.nonce), 4); +# ifdef XMRIG_FEATURE_TLS + if (m_pool.isWSS() && (m_apiVersion == API_DERO) && (m_pool.algorithm().id() == Algorithm::ASTROBWT_DERO_2)) { + char buf[256]; + const int n = snprintf(buf, sizeof(buf), "{\"jobid\":\"%s\",\"mbl_blob\":\"%s\"}", m_job.id().data(), data); + if (0 <= n && n < static_cast(sizeof(buf))) { + return WSSWrite(buf, n) ? 1 : -1; + } + return -1; + } +# endif + if (m_blocktemplate.hasMinerSignature()) { Cvt::toHex(data + sig_offset * 2, 128, result.minerSignature(), 64); } @@ -193,19 +235,20 @@ void xmrig::DaemonClient::connect() setState(ConnectingState); - if (!m_walletAddress.isValid()) { - return connectError("Invalid wallet address."); - } - if (!m_coin.isValid() && !m_pool.algorithm().isValid()) { return connectError("Invalid algorithm."); } - if ((m_pool.algorithm() == Algorithm::ASTROBWT_DERO) || (m_coin == Coin::DERO)) { + const xmrig::Algorithm algo = m_pool.algorithm(); + if ((algo == Algorithm::ASTROBWT_DERO) || (algo == Algorithm::ASTROBWT_DERO_2) || (m_coin == Coin::DERO) || (m_coin == Coin::DERO_HE)) { m_apiVersion = API_DERO; } - if (m_pool.zmq_port() >= 0) { + if ((m_apiVersion == API_MONERO) && !m_walletAddress.isValid()) { + return connectError("Invalid wallet address."); + } + + if ((m_pool.zmq_port() >= 0) || m_pool.isWSS()) { m_dns = Dns::resolve(m_pool.host(), this); } else { @@ -306,6 +349,9 @@ void xmrig::DaemonClient::onTimer(const Timer *) connect(); } else if (m_state == ConnectedState) { + if (m_pool.isWSS()) { + return; + } if (m_apiVersion == API_DERO) { rpcSend(JsonRequest::create(m_sequence, "get_info")); } @@ -330,26 +376,35 @@ void xmrig::DaemonClient::onResolved(const DnsRecords &records, int status, cons } - delete m_ZMQSocket; - - const auto &record = records.get(); m_ip = record.ip(); auto req = new uv_connect_t; req->data = m_storage.ptr(m_key); - m_ZMQSocket = new uv_tcp_t; - m_ZMQSocket->data = m_storage.ptr(m_key); + uv_tcp_t* s = new uv_tcp_t; + s->data = m_storage.ptr(m_key); - uv_tcp_init(uv_default_loop(), m_ZMQSocket); - uv_tcp_nodelay(m_ZMQSocket, 1); + uv_tcp_init(uv_default_loop(), s); + uv_tcp_nodelay(s, 1); # ifndef WIN32 - uv_tcp_keepalive(m_ZMQSocket, 1, 60); + uv_tcp_keepalive(s, 1, 60); # endif - uv_tcp_connect(req, m_ZMQSocket, record.addr(m_pool.zmq_port()), onZMQConnect); +# ifdef XMRIG_FEATURE_TLS + if (m_pool.isWSS()) { + delete m_wss.m_socket; + m_wss.m_socket = s; + uv_tcp_connect(req, s, record.addr(m_pool.port()), onWSSConnect); + } + else +# endif + if (m_pool.zmq_port() > 0) { + delete m_ZMQSocket; + m_ZMQSocket = s; + uv_tcp_connect(req, s, record.addr(m_pool.zmq_port()), onZMQConnect); + } } @@ -396,7 +451,7 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) ); # endif - m_blockhashingblob = Json::getString(params, "blockhashing_blob"); + m_blockhashingblob = Json::getString(params, kBlockhashingBlob); if (m_blocktemplate.hasMinerSignature()) { if (m_pool.spendSecretKey().isEmpty()) { @@ -589,6 +644,12 @@ void xmrig::DaemonClient::retry() setState(ConnectingState); } +# ifdef XMRIG_FEATURE_TLS + if (m_wss.m_socket) { + uv_close(reinterpret_cast(m_wss.m_socket), onWSSClose); + } + else +# endif if ((m_ZMQConnectionState != ZMQ_NOT_CONNECTED) && (m_ZMQConnectionState != ZMQ_DISCONNECTING)) { uv_close(reinterpret_cast(m_ZMQSocket), onZMQClose); } @@ -913,3 +974,373 @@ bool xmrig::DaemonClient::ZMQClose(bool shutdown) return false; } + + +#ifdef XMRIG_FEATURE_TLS +void xmrig::DaemonClient::onWSSConnect(uv_connect_t* req, int status) +{ + DaemonClient* client = getClient(req->data); + delete req; + + if (!client) { + return; + } + + if (status < 0) { + LOG_ERR("%s " RED("WSS connect error: ") RED_BOLD("\"%s\""), client->tag(), uv_strerror(status)); + client->retry(); + return; + } + + client->WSSConnected(); +} + + +void xmrig::DaemonClient::onWSSRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) +{ + DaemonClient* client = getClient(stream->data); + if (client) { + client->WSSRead(nread, buf); + } + + NetBuffer::release(buf); +} + + +void xmrig::DaemonClient::onWSSClose(uv_handle_t* handle) +{ + DaemonClient* client = getClient(handle->data); + if (client) { +# ifdef APP_DEBUG + LOG_DEBUG(CYAN("%s") BLACK_BOLD(" disconnected"), client->m_pool.url().data()); +# endif + client->m_wss.cleanup(); + client->retry(); + } +} + + +void xmrig::DaemonClient::onWSSShutdown(uv_handle_t* handle) +{ + DaemonClient* client = getClient(handle->data); + if (client) { +# ifdef APP_DEBUG + LOG_DEBUG(CYAN("%s") BLACK_BOLD(" shutdown"), client->m_pool.url().data()); +# endif + client->m_wss.cleanup(); + m_storage.remove(client->m_key); + } +} + + +void xmrig::DaemonClient::WSSConnected() +{ + m_wss.m_ctx = SSL_CTX_new(SSLv23_method()); + m_wss.m_write = BIO_new(BIO_s_mem()); + m_wss.m_read = BIO_new(BIO_s_mem()); + + SSL_CTX_set_options(m_wss.m_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + m_wss.m_ssl = SSL_new(m_wss.m_ctx); + SSL_set_connect_state(m_wss.m_ssl); + SSL_set_bio(m_wss.m_ssl, m_wss.m_read, m_wss.m_write); + SSL_do_handshake(m_wss.m_ssl); + + if (WSSWrite(nullptr, 0)) { + uv_read_start(reinterpret_cast(m_wss.m_socket), NetBuffer::onAlloc, onWSSRead); + } +} + + +bool xmrig::DaemonClient::WSSWrite(const char* data, size_t size) +{ + if (!m_wss.m_socket) { + return false; + } + + if (data && size) { +# ifdef APP_DEBUG + LOG_DEBUG(CYAN("%s") BLACK_BOLD(" write ") CYAN_BOLD("%zu") BLACK_BOLD(" bytes") " %s", m_pool.url().data(), size, data); +# endif + + if (!m_wss.m_handshake) { + WSS::Header h{}; + h.fin = 1; + h.mask = 1; + h.opcode = 1; + + uint8_t size_buf[8]; + if (size < 126) { + h.payload_len = static_cast(size); + } + else if (size < 65536) { + h.payload_len = 126; + size_buf[0] = static_cast(size >> 8); + size_buf[1] = static_cast(size & 0xFF); + } + else { + h.payload_len = 127; + uint64_t k = size; + for (int i = 7; i >= 0; --i, k >>= 8) { + size_buf[i] = static_cast(k & 0xFF); + } + } + + // Header + SSL_write(m_wss.m_ssl, &h, sizeof(h)); + + // Optional extended payload length + if (h.payload_len == 126) SSL_write(m_wss.m_ssl, size_buf, 2); + if (h.payload_len == 127) SSL_write(m_wss.m_ssl, size_buf, 8); + + // Masking-key + SSL_write(m_wss.m_ssl, "\0\0\0\0", 4); + } + + SSL_write(m_wss.m_ssl, data, static_cast(size)); + } + + uv_buf_t buf; + buf.len = BIO_get_mem_data(m_wss.m_write, &buf.base); + + if (buf.len == 0) { + return true; + } + + const int rc = uv_try_write(reinterpret_cast(m_wss.m_socket), &buf, 1); + + BIO_reset(m_wss.m_write); + + if (static_cast(rc) == buf.len) { + return true; + } + + LOG_ERR("%s " RED("WSS write failed, rc = %d"), tag(), rc); + WSSClose(); + return false; +} + + +void xmrig::DaemonClient::WSSRead(ssize_t nread, const uv_buf_t* read_buf) +{ + if (nread <= 0) { + LOG_ERR("%s " RED("WSS read failed, nread = %" PRId64), tag(), nread); + WSSClose(); + return; + } + + BIO_write(m_wss.m_read, read_buf->base, static_cast(nread)); + + if (!SSL_is_init_finished(m_wss.m_ssl)) { + const int rc = SSL_connect(m_wss.m_ssl); + + if ((rc < 0) && (SSL_get_error(m_wss.m_ssl, rc) == SSL_ERROR_WANT_READ)) { + WSSWrite(nullptr, 0); + } + else if (rc == 1) { + // login + static constexpr char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + char key[25]; + std::random_device r; + + for (int i = 0; i < 21; ++i) { + key[i] = Base64[r() % 64]; + } + + key[21] = Base64[0]; + key[22] = '='; + key[23] = '='; + key[24] = '\0'; + + const int n = snprintf(m_wss.m_buf, sizeof(m_wss.m_buf), kWSSLogin, m_pool.user().data(), m_pool.host().data(), key); + if (0 <= n && n < static_cast(sizeof(m_wss.m_buf))) { + WSSWrite(m_wss.m_buf, n); + } + else { + WSSClose(); + } + } + + return; + } + + int n = 0; + while ((n = SSL_read(m_wss.m_ssl, m_wss.m_buf, sizeof(m_wss.m_buf))) > 0) { + m_wss.m_data.insert(m_wss.m_data.end(), m_wss.m_buf, m_wss.m_buf + n); + + // Skip the first message (HTTP upgrade response) + if (m_wss.m_handshake) { + const size_t len = m_wss.m_data.size(); + if (len >= 4) { + for (size_t k = 0; k <= len - 4; ++k) { + if (memcmp(m_wss.m_data.data() + k, "\r\n\r\n", 4) == 0) { + m_wss.m_handshake = false; + m_wss.m_data.erase(m_wss.m_data.begin(), m_wss.m_data.begin() + k + 4); + break; + } + } + } + continue; + } + + const uint8_t* p0 = reinterpret_cast(m_wss.m_data.data()); + const uint8_t* p = p0; + const uint8_t* e = p0 + m_wss.m_data.size(); + + if (e - p < static_cast(sizeof(WSS::Header))) + continue; + + const WSS::Header* h = reinterpret_cast(p); + p += sizeof(WSS::Header); + + uint64_t len = h->payload_len; + + if (len == 126) { + if (e - p < static_cast(sizeof(uint16_t))) { + continue; + } + len = 0; + for (size_t i = 0; i < sizeof(uint16_t); ++i, ++p) { + len = (len << 8) | *p; + } + } + else if (len == 127) { + if (e - p < static_cast(sizeof(uint64_t))) { + continue; + } + len = 0; + for (size_t i = 0; i < sizeof(uint64_t); ++i, ++p) { + len = (len << 8) | *p; + } + } + + uint8_t mask_key[4] = {}; + if (h->mask) { + if (e - p < 4) + continue; + memcpy(mask_key, p, 4); + p += 4; + } + + if (static_cast(e - p) < len) + continue; + + for (uint64_t i = 0; i < len; ++i) { + m_wss.m_message.push_back(p[i] ^ mask_key[i % 4]); + } + p += len; + + m_wss.m_data.erase(m_wss.m_data.begin(), m_wss.m_data.begin() + (p - p0)); + + if (h->fin) { + if (m_wss.m_message.back() == '\n') { + m_wss.m_message.back() = '\0'; + } + else { + m_wss.m_message.push_back('\0'); + } + WSSParse(); + m_wss.m_message.clear(); + } + } +} + + +void xmrig::DaemonClient::WSSParse() +{ +# ifdef APP_DEBUG + LOG_DEBUG(CYAN("%s") BLACK_BOLD(" read ") CYAN_BOLD("%zu") BLACK_BOLD(" bytes") " %s", m_pool.url().data(), m_wss.m_message.size(), m_wss.m_message.data()); +# endif + + using namespace rapidjson; + + Document doc; + if (doc.ParseInsitu(m_wss.m_message.data()).HasParseError() || !doc.IsObject()) { + if (!isQuiet()) { + LOG_ERR("%s " RED("JSON decode failed: ") RED_BOLD("\"%s\""), tag(), GetParseError_En(doc.GetParseError())); + } + + return retry(); + } + + if (doc.HasMember(kLastError)) { + String err = Json::getString(doc, kLastError, ""); + if (!err.isEmpty()) { + LOG_ERR("%s " RED_BOLD("\"%s\""), tag(), err.data()); + return; + } + } + + if (doc.HasMember(kBlockhashingBlob)) { + Job job(false, m_pool.algorithm(), String()); + + m_blockhashingblob = Json::getString(doc, kBlockhashingBlob, ""); + if (m_blockhashingblob.isEmpty()) { + LOG_ERR("%s " RED_BOLD("blockhashing_blob is empty"), tag()); + return; + } + job.setBlob(m_blockhashingblob); + memset(job.blob() + job.nonceOffset(), 0, job.nonceSize()); + + job.setHeight(Json::getUint64(doc, kHeight)); + job.setDiff(Json::getUint64(doc, "difficultyuint64")); + //job.setDiff(100000); + + m_currentJobId = Json::getString(doc, "jobid"); + job.setId(m_currentJobId); + + m_job = std::move(job); + + if (m_state == ConnectingState) { + setState(ConnectedState); + } + + const uint64_t blocks = Json::getUint64(doc, "blocks"); + const uint64_t miniblocks = Json::getUint64(doc, "miniblocks"); + + if ((blocks != m_wss.m_blocks) || (miniblocks != m_wss.m_miniblocks)) { + LOG_INFO("%s " GREEN_BOLD("%" PRIu64 " blocks, %" PRIu64 " mini blocks"), tag(), blocks, miniblocks); + m_wss.m_blocks = blocks; + m_wss.m_miniblocks = miniblocks; + } + + m_listener->onJobReceived(this, m_job, doc); + return; + } +} + + +bool xmrig::DaemonClient::WSSClose(bool shutdown) +{ + if (m_wss.m_socket && (uv_is_closing(reinterpret_cast(m_wss.m_socket)) == 0)) { + uv_close(reinterpret_cast(m_wss.m_socket), shutdown ? onWSSShutdown : onWSSClose); + return true; + } + + return false; +} + + +void xmrig::DaemonClient::WSS::cleanup() +{ + delete m_socket; + m_socket = nullptr; + + if (m_ctx) { + SSL_CTX_free(m_ctx); + m_ctx = nullptr; + } + if (m_ssl) { + SSL_free(m_ssl); + m_ssl = nullptr; + } + + m_read = nullptr; + m_write = nullptr; + m_handshake = true; + m_blocks = 0; + m_miniblocks = 0; + m_data.clear(); + m_message.clear(); +} +#endif diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index 5a6ca8ca8..73f47e2d1 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -39,6 +39,12 @@ using uv_handle_t = struct uv_handle_s; using uv_stream_t = struct uv_stream_s; using uv_tcp_t = struct uv_tcp_s; +#ifdef XMRIG_FEATURE_TLS +using BIO = struct bio_st; +using SSL = struct ssl_st; +using SSL_CTX = struct ssl_ctx_st; +#endif + namespace xmrig { @@ -57,6 +63,7 @@ public: protected: bool disconnect() override; bool isTLS() const override; + bool isWSS() const override; int64_t submit(const JobResult &result) override; void connect() override; void connect(const Pool &pool) override; @@ -136,6 +143,44 @@ private: std::vector m_ZMQSendBuf; std::vector m_ZMQRecvBuf; + +# ifdef XMRIG_FEATURE_TLS + static void onWSSConnect(uv_connect_t* req, int status); + static void onWSSRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); + static void onWSSClose(uv_handle_t* handle); + static void onWSSShutdown(uv_handle_t* handle); + + void WSSConnected(); + bool WSSWrite(const char* data, size_t size); + void WSSRead(ssize_t nread, const uv_buf_t* buf); + void WSSParse(); + bool WSSClose(bool shutdown = false); + + struct WSS { + struct Header + { + uint8_t opcode : 4; + uint8_t reserved : 3; + uint8_t fin : 1; + uint8_t payload_len : 7; + uint8_t mask : 1; + }; + + uv_tcp_t* m_socket = nullptr; + SSL_CTX* m_ctx = nullptr; + BIO* m_read = nullptr; + BIO* m_write = nullptr; + SSL* m_ssl = nullptr; + char m_buf[512] = {}; + bool m_handshake = true; + uint64_t m_blocks = 0; + uint64_t m_miniblocks = 0; + std::vector m_data; + std::vector m_message; + + void cleanup(); + } m_wss; +# endif }; diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index 8465ec0bc..fd002d0e3 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -164,6 +164,18 @@ void xmrig::Job::setSigKey(const char *sig_key) } +int32_t xmrig::Job::nonceOffset() const +{ + auto f = algorithm().family(); + if (f == Algorithm::KAWPOW) return 32; + if (f == Algorithm::GHOSTRIDER) return 76; + + auto id = algorithm().id(); + if (id == Algorithm::ASTROBWT_DERO_2) return 44; + + return 39; +} + uint32_t xmrig::Job::getNumTransactions() const { if (!(m_algorithm.isCN() || m_algorithm.family() == Algorithm::RANDOM_X)) { diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 3bad33d53..3fb31baa5 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -76,7 +76,7 @@ public: inline const String &poolWallet() const { return m_poolWallet; } inline const uint32_t *nonce() const { return reinterpret_cast(m_blob + nonceOffset()); } inline const uint8_t *blob() const { return m_blob; } - inline int32_t nonceOffset() const { auto f = algorithm().family(); return (f == Algorithm::KAWPOW) ? 32 : ((f == Algorithm::GHOSTRIDER) ? 76 : 39); } + int32_t nonceOffset() const; inline size_t nonceSize() const { return (algorithm().family() == Algorithm::KAWPOW) ? 8 : 4; } inline size_t size() const { return m_size; } inline uint32_t *nonce() { return reinterpret_cast(m_blob + nonceOffset()); } diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index 7a58f4cb5..e11e8717f 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -76,6 +76,7 @@ const char *Pool::kSelfSelect = "self-select"; const char *Pool::kSOCKS5 = "socks5"; const char *Pool::kSubmitToOrigin = "submit-to-origin"; const char *Pool::kTls = "tls"; +const char *Pool::kWSS = "wss"; const char *Pool::kUrl = "url"; const char *Pool::kUser = "user"; const char *Pool::kSpendSecretKey = "spend-secret-key"; @@ -93,7 +94,7 @@ xmrig::Pool::Pool(const char *url) : } -xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, const char* spendSecretKey, int keepAlive, bool nicehash, bool tls, Mode mode) : +xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, const char* spendSecretKey, int keepAlive, bool nicehash, bool tls, bool wss, Mode mode) : m_keepAlive(keepAlive), m_mode(mode), m_flags(1 << FLAG_ENABLED), @@ -105,6 +106,7 @@ xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char { m_flags.set(FLAG_NICEHASH, nicehash || strstr(host, kNicehashHost)); m_flags.set(FLAG_TLS, tls); + m_flags.set(FLAG_WSS, wss); } @@ -132,6 +134,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) : m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true)); m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash) || m_url.host().contains(kNicehashHost)); m_flags.set(FLAG_TLS, Json::getBool(object, kTls) || m_url.isTLS()); + m_flags.set(FLAG_WSS, Json::getBool(object, kWSS) || m_url.isWSS()); setKeepAlive(Json::getValue(object, kKeepalive)); @@ -293,6 +296,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator); obj.AddMember(StringRef(kTls), isTLS(), allocator); + obj.AddMember(StringRef(kWSS), isWSS(), allocator); obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator); obj.AddMember(StringRef(kDaemon), m_mode == MODE_DAEMON, allocator); obj.AddMember(StringRef(kSOCKS5), m_proxy.toJSON(doc), allocator); diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index 78684510f..54e38f8dc 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -69,10 +69,12 @@ public: static const char *kSOCKS5; static const char *kSubmitToOrigin; static const char *kTls; + static const char* kWSS; static const char *kUrl; static const char *kUser; static const char* kSpendSecretKey; static const char* kDaemonZMQPort; + static const char* kDaemonWSSPort; static const char *kNicehashHost; constexpr static int kKeepAliveTimeout = 60; @@ -80,7 +82,7 @@ public: constexpr static uint64_t kDefaultPollInterval = 1000; Pool() = default; - Pool(const char *host, uint16_t port, const char *user, const char *password, const char* spendSecretKey, int keepAlive, bool nicehash, bool tls, Mode mode); + Pool(const char *host, uint16_t port, const char *user, const char *password, const char* spendSecretKey, int keepAlive, bool nicehash, bool tls, bool wss, Mode mode); Pool(const char *url); Pool(const rapidjson::Value &object); @@ -93,6 +95,7 @@ public: inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); } inline bool isTLS() const { return m_flags.test(FLAG_TLS) || m_url.isTLS(); } + inline bool isWSS() const { return m_flags.test(FLAG_WSS) || m_url.isWSS(); } inline bool isValid() const { return m_url.isValid(); } inline const Algorithm &algorithm() const { return m_algorithm; } inline const Coin &coin() const { return m_coin; } @@ -135,6 +138,7 @@ private: FLAG_ENABLED, FLAG_NICEHASH, FLAG_TLS, + FLAG_WSS, FLAG_MAX }; diff --git a/src/base/net/stratum/SelfSelectClient.h b/src/base/net/stratum/SelfSelectClient.h index c73198a5a..a68dbcfc2 100644 --- a/src/base/net/stratum/SelfSelectClient.h +++ b/src/base/net/stratum/SelfSelectClient.h @@ -49,6 +49,7 @@ protected: inline bool hasExtension(Extension extension) const noexcept override { return m_client->hasExtension(extension); } inline bool isEnabled() const override { return m_client->isEnabled(); } inline bool isTLS() const override { return m_client->isTLS(); } + inline bool isWSS() const override { return m_client->isWSS(); } inline const char *mode() const override { return m_client->mode(); } inline const char *tag() const override { return m_client->tag(); } inline const char *tlsFingerprint() const override { return m_client->tlsFingerprint(); } diff --git a/src/base/net/stratum/Url.cpp b/src/base/net/stratum/Url.cpp index 7904a445d..3bb47db1e 100644 --- a/src/base/net/stratum/Url.cpp +++ b/src/base/net/stratum/Url.cpp @@ -39,6 +39,7 @@ static const char kSOCKS5[] = "socks5://"; #ifdef XMRIG_FEATURE_HTTP static const char kDaemonHttp[] = "daemon+http://"; static const char kDaemonHttps[] = "daemon+https://"; +static const char kDaemonWss[] = "daemon+wss://"; #endif } // namespace xmrig @@ -103,6 +104,11 @@ bool xmrig::Url::parse(const char *url) m_scheme = DAEMON; m_tls = false; } + else if (strncasecmp(url, kDaemonWss, sizeof(kDaemonWss) - 1) == 0) { + m_scheme = DAEMON; + m_tls = true; + m_wss = true; + } # endif else { return false; diff --git a/src/base/net/stratum/Url.h b/src/base/net/stratum/Url.h index 6882631e2..f8ccf7693 100644 --- a/src/base/net/stratum/Url.h +++ b/src/base/net/stratum/Url.h @@ -41,6 +41,7 @@ public: Url(const char *host, uint16_t port, bool tls = false, Scheme scheme = UNSPECIFIED); inline bool isTLS() const { return m_tls; } + inline bool isWSS() const { return m_wss; } inline bool isValid() const { return !m_host.isNull() && m_port > 0; } inline const String &host() const { return m_host; } inline const String &url() const { return m_url; } @@ -57,6 +58,7 @@ protected: bool parseIPv6(const char *addr); bool m_tls = false; + bool m_wss = false; Scheme m_scheme = UNSPECIFIED; String m_host; String m_url; diff --git a/src/base/net/stratum/benchmark/BenchClient.h b/src/base/net/stratum/benchmark/BenchClient.h index c29e42e00..1bd281614 100644 --- a/src/base/net/stratum/benchmark/BenchClient.h +++ b/src/base/net/stratum/benchmark/BenchClient.h @@ -41,6 +41,7 @@ public: inline bool hasExtension(Extension) const noexcept override { return false; } inline bool isEnabled() const override { return true; } inline bool isTLS() const override { return false; } + inline bool isWSS() const override { return false; } inline const char *mode() const override { return "benchmark"; } inline const char *tlsFingerprint() const override { return nullptr; } inline const char *tlsVersion() const override { return nullptr; } diff --git a/src/base/tools/bswap_64.h b/src/base/tools/bswap_64.h index 96335c64e..462a33553 100644 --- a/src/base/tools/bswap_64.h +++ b/src/base/tools/bswap_64.h @@ -23,10 +23,12 @@ #include #define bswap_64(x) _byteswap_uint64(x) +#define bswap_32(x) _byteswap_ulong(x) #elif defined __GNUC__ #define bswap_64(x) __builtin_bswap64(x) +#define bswap_32(x) __builtin_bswap32(x) #else diff --git a/src/crypto/astrobwt/AstroBWT.cpp b/src/crypto/astrobwt/AstroBWT.cpp index 9fd2db60b..2ae649b2f 100644 --- a/src/crypto/astrobwt/AstroBWT.cpp +++ b/src/crypto/astrobwt/AstroBWT.cpp @@ -25,6 +25,7 @@ #include "base/crypto/sha3.h" #include "base/tools/bswap_64.h" #include "crypto/cn/CryptoNight.h" +#include "crypto/astrobwt/sort_indices2.h" #include @@ -433,6 +434,45 @@ bool xmrig::astrobwt::astrobwt_dero(const void* input_data, uint32_t input_size, } +bool xmrig::astrobwt::astrobwt_dero_v2(const void* input_data, uint32_t input_size, void* scratchpad, uint8_t* output_hash) +{ + constexpr size_t N = 9973; + constexpr size_t STRIDE = 10240; + + alignas(8) uint8_t key[32]; + uint8_t* scratchpad_ptr = (uint8_t*)(scratchpad) + 64; + uint8_t* v = scratchpad_ptr; + uint32_t* indices = (uint32_t*)(scratchpad_ptr + STRIDE); + uint32_t* tmp_indices = (uint32_t*)(scratchpad_ptr + STRIDE * 5); + +#ifdef ASTROBWT_AVX2 + if (hasAVX2) { + SHA3_256_AVX2_ASM(input_data, input_size, key); + Salsa20_XORKeyStream_AVX256(key, v, N); + } + else +#endif + { + sha3_HashBuffer(256, SHA3_FLAGS_NONE, input_data, input_size, key, sizeof(key)); + Salsa20_XORKeyStream(key, v, N); + } + + sort_indices_astrobwt_v2(N, v, indices, tmp_indices); + +#ifdef ASTROBWT_AVX2 + if (hasAVX2) { + SHA3_256_AVX2_ASM(indices, N * 2, output_hash); + } + else +#endif + { + sha3_HashBuffer(256, SHA3_FLAGS_NONE, indices, N * 2, output_hash, 32); + } + + return true; +} + + void xmrig::astrobwt::init() { if (!astrobwtInitialized) { @@ -450,3 +490,10 @@ void xmrig::astrobwt::single_hash(const uint8_t { astrobwt_dero(input, static_cast(size), ctx[0]->memory, output, std::numeric_limits::max(), true); } + + +template<> +void xmrig::astrobwt::single_hash(const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx** ctx, uint64_t) +{ + astrobwt_dero_v2(input, static_cast(size), ctx[0]->memory, output); +} diff --git a/src/crypto/astrobwt/AstroBWT.h b/src/crypto/astrobwt/AstroBWT.h index 236b3ce47..15dfa361e 100644 --- a/src/crypto/astrobwt/AstroBWT.h +++ b/src/crypto/astrobwt/AstroBWT.h @@ -32,6 +32,7 @@ namespace xmrig { namespace astrobwt { bool astrobwt_dero(const void* input_data, uint32_t input_size, void* scratchpad, uint8_t* output_hash, int stage2_max_size, bool avx2); +bool astrobwt_dero_v2(const void* input_data, uint32_t input_size, void* scratchpad, uint8_t* output_hash); void init(); template @@ -40,5 +41,7 @@ void single_hash(const uint8_t* input, size_t size, uint8_t* output, cryptonight template<> void single_hash(const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx** ctx, uint64_t); +template<> +void single_hash(const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx** ctx, uint64_t); }} // namespace xmrig::astrobwt diff --git a/src/crypto/astrobwt/sort_indices2.cpp b/src/crypto/astrobwt/sort_indices2.cpp new file mode 100644 index 000000000..60603b84b --- /dev/null +++ b/src/crypto/astrobwt/sort_indices2.cpp @@ -0,0 +1,208 @@ +/* XMRig + * Copyright (c) 2018 Lee Clagett + * Copyright (c) 2018-2019 tevador + * Copyright (c) 2000 Transmeta Corporation + * Copyright (c) 2004-2008 H. Peter Anvin + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 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/astrobwt/sort_indices2.h" +#include "base/tools/bswap_64.h" +#include + + +#ifdef __GNUC__ +#define NOINLINE __attribute__((noinline)) +#define RESTRICT __restrict__ +#elif _MSC_VER +#define NOINLINE __declspec(noinline) +#define RESTRICT __restrict +#else +#define NOINLINE +#define RESTRICT +#endif + + +#if __has_cpp_attribute(unlikely) +#define UNLIKELY(X) (X) [[unlikely]] +#elif defined __GNUC__ +#define UNLIKELY(X) (__builtin_expect((X), 0)) +#else +#define UNLIKELY(X) (X) +#endif + + +static NOINLINE void fix(const uint8_t* RESTRICT v, uint32_t* RESTRICT indices, int32_t i) +{ + uint32_t prev_t = indices[i - 1]; + uint32_t t = indices[i]; + + const uint32_t data_a = bswap_32(*(const uint32_t*)(v + (t & 0xFFFF) + 2)); + if (data_a < bswap_32(*(const uint32_t*)(v + (prev_t & 0xFFFF) + 2))) + { + const uint32_t t2 = prev_t; + int32_t j = i - 1; + do + { + indices[j + 1] = prev_t; + --j; + + if (j < 0) { + break; + } + + prev_t = indices[j]; + } while (((t ^ prev_t) <= 0xFFFF) && (data_a < bswap_32(*(const uint32_t*)(v + (prev_t & 0xFFFF) + 2)))); + indices[j + 1] = t; + t = t2; + } +} + + +static NOINLINE void sort_indices(uint32_t N, const uint8_t* RESTRICT v, uint32_t* RESTRICT indices, uint32_t* RESTRICT tmp_indices) +{ + uint8_t byte_counters[2][256] = {}; + uint32_t counters[2][256]; + + { +#define ITER(X) ++byte_counters[1][v[i + X]]; + + enum { unroll = 12 }; + + uint32_t i = 0; + const uint32_t n = N - (unroll - 1); + for (; i < n; i += unroll) { + ITER(0); ITER(1); ITER(2); ITER(3); ITER(4); ITER(5); ITER(6); ITER(7); ITER(8); ITER(9); ITER(10); ITER(11); + } + for (; i < N; ++i) { + ITER(0); + } + memcpy(&byte_counters[0], &byte_counters[1], 256); + --byte_counters[0][v[0]]; + +#undef ITER + } + + { + uint32_t c0 = byte_counters[0][0]; + uint32_t c1 = byte_counters[1][0] - 1; + counters[0][0] = c0; + counters[1][0] = c1; + uint8_t* src = &byte_counters[0][0] + 1; + uint32_t* dst = &counters[0][0] + 1; + const uint8_t* const e = &byte_counters[0][0] + 256; + do { + c0 += src[0]; + c1 += src[256]; + dst[0] = c0; + dst[256] = c1; + ++src; + ++dst; + } while (src < e); + } + + { +#define ITER(X) \ + do { \ + const uint32_t byte0 = v[i - X + 0]; \ + const uint32_t byte1 = v[i - X + 1]; \ + tmp_indices[counters[0][byte1]--] = (byte0 << 24) | (byte1 << 16) | (i - X); \ + } while (0) + + enum { unroll = 8 }; + + uint32_t i = N; + for (; i >= unroll; i -= unroll) { + ITER(1); ITER(2); ITER(3); ITER(4); ITER(5); ITER(6); ITER(7); ITER(8); + } + for (; i > 0; --i) { + ITER(1); + } + +#undef ITER + } + + { +#define ITER(X) \ + do { \ + const uint32_t data = tmp_indices[i - X]; \ + indices[counters[1][data >> 24]--] = data; \ + } while (0) + + enum { unroll = 8 }; + + uint32_t i = N; + for (; i >= unroll; i -= unroll) { + ITER(1); ITER(2); ITER(3); ITER(4); ITER(5); ITER(6); ITER(7); ITER(8); + } + for (; i > 0; --i) { + ITER(1); + } + +#undef ITER + } + + { +#define ITER(X) do { if UNLIKELY(a[X * 2] == a[(X + 1) * 2]) fix(v, indices, i + X); } while (0) + + enum { unroll = 16 }; + + uint32_t i = 1; + const uint32_t n = N - (unroll - 1); + const uint16_t* a = ((const uint16_t*)indices) + 1; + + for (; i < n; i += unroll, a += unroll * 2) { + ITER(0); ITER(1); ITER(2); ITER(3); ITER(4); ITER(5); ITER(6); ITER(7); + ITER(8); ITER(9); ITER(10); ITER(11); ITER(12); ITER(13); ITER(14); ITER(15); + } + for (; i < N; ++i, a += 2) { + ITER(0); + } + +#undef ITER + } + + { +#define ITER(X) a[X] = b[X * 2]; + + enum { unroll = 32 }; + + uint16_t* a = (uint16_t*)indices; + uint16_t* b = (uint16_t*)indices; + uint16_t* e = (uint16_t*)(indices + (N - (unroll - 1))); + + for (; a < e; a += unroll, b += unroll * 2) { + ITER(0); ITER(1); ITER(2); ITER(3); ITER(4); ITER(5); ITER(6); ITER(7); + ITER(8); ITER(9); ITER(10); ITER(11); ITER(12); ITER(13); ITER(14); ITER(15); + ITER(16); ITER(17); ITER(18); ITER(19); ITER(20); ITER(21); ITER(22); ITER(23); + ITER(24); ITER(25); ITER(26); ITER(27); ITER(28); ITER(29); ITER(30); ITER(31); + } + + e = (uint16_t*)(indices + N); + for (; a < e; ++a, b += 2) { + ITER(0); + } + +#undef ITER + } +} + + +void sort_indices_astrobwt_v2(uint32_t N, const uint8_t* v, uint32_t* indices, uint32_t* tmp_indices) +{ + sort_indices(N, v, indices, tmp_indices); +} diff --git a/src/crypto/astrobwt/sort_indices2.h b/src/crypto/astrobwt/sort_indices2.h new file mode 100644 index 000000000..3dd3a7515 --- /dev/null +++ b/src/crypto/astrobwt/sort_indices2.h @@ -0,0 +1,26 @@ +/* XMRig + * Copyright (c) 2018 Lee Clagett + * Copyright (c) 2018-2019 tevador + * Copyright (c) 2000 Transmeta Corporation + * Copyright (c) 2004-2008 H. Peter Anvin + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 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 + + +void sort_indices_astrobwt_v2(uint32_t N, const uint8_t* v, uint32_t* indices, uint32_t* tmp_indices); diff --git a/src/crypto/cn/CnHash.cpp b/src/crypto/cn/CnHash.cpp index a1ef90151..095b0eb0e 100644 --- a/src/crypto/cn/CnHash.cpp +++ b/src/crypto/cn/CnHash.cpp @@ -379,6 +379,10 @@ xmrig::CnHash::CnHash() m_map[Algorithm::ASTROBWT_DERO] = new cn_hash_fun_array{}; m_map[Algorithm::ASTROBWT_DERO]->data[AV_SINGLE][Assembly::NONE] = astrobwt::single_hash; m_map[Algorithm::ASTROBWT_DERO]->data[AV_SINGLE_SOFT][Assembly::NONE] = astrobwt::single_hash; + + m_map[Algorithm::ASTROBWT_DERO_2] = new cn_hash_fun_array{}; + m_map[Algorithm::ASTROBWT_DERO_2]->data[AV_SINGLE][Assembly::NONE] = astrobwt::single_hash; + m_map[Algorithm::ASTROBWT_DERO_2]->data[AV_SINGLE_SOFT][Assembly::NONE] = astrobwt::single_hash; # endif # ifdef XMRIG_ALGO_GHOSTRIDER diff --git a/src/crypto/cn/CryptoNight_test.h b/src/crypto/cn/CryptoNight_test.h index 1df168e02..9bec3cd82 100644 --- a/src/crypto/cn/CryptoNight_test.h +++ b/src/crypto/cn/CryptoNight_test.h @@ -447,6 +447,19 @@ const static uint8_t astrobwt_dero_test_out[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +// "astrobwt/v2" +const static uint8_t astrobwt_dero_2_test_out[256] = { + 0x48, 0x9E, 0xD2, 0x66, 0x14, 0x27, 0x98, 0x65, 0x03, 0xFB, 0x87, 0x25, 0xE1, 0xD3, 0x98, 0xDA, + 0x27, 0xEE, 0x25, 0x3D, 0xB4, 0x37, 0x87, 0x98, 0xBF, 0x5A, 0x5C, 0x94, 0xEE, 0x0C, 0xE2, 0x2A, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; #endif diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index be9aad6a8..3d4003406 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -70,9 +70,9 @@ xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener # endif # ifdef XMRIG_FEATURE_TLS - m_pools.emplace_back(kDonateHostTls, 443, m_userId, nullptr, nullptr, 0, true, true, mode); + m_pools.emplace_back(kDonateHostTls, 443, m_userId, nullptr, nullptr, 0, true, true, false, mode); # endif - m_pools.emplace_back(kDonateHost, 3333, m_userId, nullptr, nullptr, 0, true, false, mode); + m_pools.emplace_back(kDonateHost, 3333, m_userId, nullptr, nullptr, 0, true, false, false, mode); if (m_pools.size() > 1) { m_strategy = new FailoverStrategy(m_pools, 10, 2, this, true); @@ -252,7 +252,7 @@ xmrig::IClient *xmrig::DonateStrategy::createProxy() const IClient *client = strategy->client(); m_tls = client->hasExtension(IClient::EXT_TLS); - Pool pool(client->pool().proxy().isValid() ? client->pool().host() : client->ip(), client->pool().port(), m_userId, client->pool().password(), client->pool().spendSecretKey(), 0, true, client->isTLS(), Pool::MODE_POOL); + Pool pool(client->pool().proxy().isValid() ? client->pool().host() : client->ip(), client->pool().port(), m_userId, client->pool().password(), client->pool().spendSecretKey(), 0, true, client->isTLS(), client->isWSS(), Pool::MODE_POOL); pool.setAlgo(client->pool().algorithm()); pool.setProxy(client->pool().proxy());