mirror of
https://github.com/xmrig/xmrig.git
synced 2024-11-16 15:57:38 +00:00
Dero HE fork support (astrobwt/v2 algorithm)
This commit is contained in:
parent
f7543ada60
commit
b5da73389f
27 changed files with 879 additions and 39 deletions
|
@ -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)
|
||||
|
|
|
@ -157,7 +157,15 @@ size_t inline generate<Algorithm::ARGON2>(Threads<CpuThreads> &threads, uint32_t
|
|||
template<>
|
||||
size_t inline generate<Algorithm::ASTROBWT>(Threads<CpuThreads>& 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
|
||||
|
||||
|
|
|
@ -224,9 +224,8 @@ bool xmrig::CpuWorker<N>::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<N>::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
|
||||
|
|
|
@ -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<uint32_t, const char *> 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<const char *, Algorithm::Id, aliasCompare> 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> xmrig::Algorithm::all(const std::function<bool(con
|
|||
CN_UPX2,
|
||||
RX_0, RX_WOW, RX_ARQ, RX_GRAFT, RX_SFX, RX_KEVA,
|
||||
AR2_CHUKWA, AR2_CHUKWA_V2, AR2_WRKZ,
|
||||
ASTROBWT_DERO,
|
||||
ASTROBWT_DERO, ASTROBWT_DERO_2,
|
||||
KAWPOW_RVN,
|
||||
GHOSTRIDER_RTM
|
||||
};
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
AR2_CHUKWA_V2 = 0x61140000, // "argon2/chukwav2" Argon2id (Chukwa v2).
|
||||
AR2_WRKZ = 0x61120000, // "argon2/wrkz" Argon2id (WRKZ)
|
||||
ASTROBWT_DERO = 0x41000000, // "astrobwt" AstroBWT (Dero)
|
||||
ASTROBWT_DERO_2 = 0x41110000, // "astrobwt/v2" AstroBWT (Dero HE)
|
||||
KAWPOW_RVN = 0x6b0f0000, // "kawpow/rvn" KawPow (RVN)
|
||||
};
|
||||
|
||||
|
@ -158,6 +159,7 @@ public:
|
|||
# ifdef XMRIG_ALGO_ASTROBWT
|
||||
static const char *kASTROBWT;
|
||||
static const char *kASTROBWT_DERO;
|
||||
static const char* kASTROBWT_DERO_2;
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_ALGO_KAWPOW
|
||||
|
|
|
@ -45,15 +45,16 @@ struct CoinInfo
|
|||
|
||||
|
||||
static const CoinInfo coinInfo[] = {
|
||||
{ Algorithm::INVALID, nullptr, nullptr, 0, 0, nullptr },
|
||||
{ Algorithm::RX_0, "XMR", "Monero", 120, 1000000000000, YELLOW_BG_BOLD( WHITE_BOLD_S " monero ") },
|
||||
{ Algorithm::CN_R, "SUMO", "Sumokoin", 240, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " sumo ") },
|
||||
{ Algorithm::RX_ARQ, "ARQ", "ArQmA", 120, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " arqma ") },
|
||||
{ Algorithm::ASTROBWT_DERO, "DERO", "DERO", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " dero ") },
|
||||
{ Algorithm::RX_GRAFT, "GRFT", "Graft", 120, 10000000000, BLUE_BG_BOLD( WHITE_BOLD_S " graft ") },
|
||||
{ Algorithm::RX_KEVA, "KVA", "Kevacoin", 0, 0, MAGENTA_BG_BOLD(WHITE_BOLD_S " keva ") },
|
||||
{ Algorithm::KAWPOW_RVN, "RVN", "Ravencoin", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " raven ") },
|
||||
{ Algorithm::RX_WOW, "WOW", "Wownero", 300, 100000000000, MAGENTA_BG_BOLD(WHITE_BOLD_S " wownero ") },
|
||||
{ Algorithm::INVALID, nullptr, nullptr, 0, 0, nullptr },
|
||||
{ Algorithm::RX_0, "XMR", "Monero", 120, 1000000000000, YELLOW_BG_BOLD( WHITE_BOLD_S " monero ") },
|
||||
{ Algorithm::CN_R, "SUMO", "Sumokoin", 240, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " sumo ") },
|
||||
{ Algorithm::RX_ARQ, "ARQ", "ArQmA", 120, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " arqma ") },
|
||||
{ Algorithm::ASTROBWT_DERO, "DERO", "DERO", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " dero ") },
|
||||
{ Algorithm::ASTROBWT_DERO_2, "DERO_HE", "DERO_HE", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " dero_he ") },
|
||||
{ Algorithm::RX_GRAFT, "GRFT", "Graft", 120, 10000000000, BLUE_BG_BOLD( WHITE_BOLD_S " graft ") },
|
||||
{ Algorithm::RX_KEVA, "KVA", "Kevacoin", 0, 0, MAGENTA_BG_BOLD(WHITE_BOLD_S " keva ") },
|
||||
{ Algorithm::KAWPOW_RVN, "RVN", "Ravencoin", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " raven ") },
|
||||
{ Algorithm::RX_WOW, "WOW", "Wownero", 300, 100000000000, MAGENTA_BG_BOLD(WHITE_BOLD_S " wownero ") },
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
SUMO,
|
||||
ARQMA,
|
||||
DERO,
|
||||
DERO_HE,
|
||||
GRAFT,
|
||||
KEVA,
|
||||
RAVEN,
|
||||
|
|
|
@ -61,6 +61,7 @@ public:
|
|||
virtual bool hasExtension(Extension extension) const noexcept = 0;
|
||||
virtual bool isEnabled() const = 0;
|
||||
virtual bool isTLS() const = 0;
|
||||
virtual bool isWSS() const = 0;
|
||||
virtual const char *mode() const = 0;
|
||||
virtual const char *tag() const = 0;
|
||||
virtual const char *tlsFingerprint() const = 0;
|
||||
|
|
|
@ -59,6 +59,8 @@ protected:
|
|||
void setPool(const Pool &pool) override;
|
||||
|
||||
protected:
|
||||
bool isWSS() const override { return false; }
|
||||
|
||||
enum SocketState {
|
||||
UnconnectedState,
|
||||
HostLookupState,
|
||||
|
|
|
@ -48,8 +48,14 @@
|
|||
#include "net/JobResult.h"
|
||||
|
||||
|
||||
#ifdef XMRIG_FEATURE_TLS
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <random>
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
@ -58,7 +64,9 @@ namespace xmrig {
|
|||
Storage<DaemonClient> 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<const uint8_t*>(&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<int>(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<uv_handle_t*>(m_wss.m_socket), onWSSClose);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
if ((m_ZMQConnectionState != ZMQ_NOT_CONNECTED) && (m_ZMQConnectionState != ZMQ_DISCONNECTING)) {
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(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<uv_stream_t*>(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<uint8_t>(size);
|
||||
}
|
||||
else if (size < 65536) {
|
||||
h.payload_len = 126;
|
||||
size_buf[0] = static_cast<uint8_t>(size >> 8);
|
||||
size_buf[1] = static_cast<uint8_t>(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<uint8_t>(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<int>(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<uv_stream_t*>(m_wss.m_socket), &buf, 1);
|
||||
|
||||
BIO_reset(m_wss.m_write);
|
||||
|
||||
if (static_cast<size_t>(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<int>(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<int>(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<uint8_t*>(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<int>(sizeof(WSS::Header)))
|
||||
continue;
|
||||
|
||||
const WSS::Header* h = reinterpret_cast<const WSS::Header*>(p);
|
||||
p += sizeof(WSS::Header);
|
||||
|
||||
uint64_t len = h->payload_len;
|
||||
|
||||
if (len == 126) {
|
||||
if (e - p < static_cast<int>(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<int>(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<uint64_t>(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<uv_handle_t*>(m_wss.m_socket)) == 0)) {
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(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
|
||||
|
|
|
@ -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<char> m_ZMQSendBuf;
|
||||
std::vector<char> 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<char> m_data;
|
||||
std::vector<char> m_message;
|
||||
|
||||
void cleanup();
|
||||
} m_wss;
|
||||
# endif
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -76,7 +76,7 @@ public:
|
|||
inline const String &poolWallet() const { return m_poolWallet; }
|
||||
inline const uint32_t *nonce() const { return reinterpret_cast<const uint32_t*>(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<uint32_t*>(m_blob + nonceOffset()); }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#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
|
||||
|
||||
|
|
|
@ -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 <limits>
|
||||
|
@ -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<xmrig::Algorithm::ASTROBWT_DERO>(const uint8_t
|
|||
{
|
||||
astrobwt_dero(input, static_cast<uint32_t>(size), ctx[0]->memory, output, std::numeric_limits<int>::max(), true);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
void xmrig::astrobwt::single_hash<xmrig::Algorithm::ASTROBWT_DERO_2>(const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx** ctx, uint64_t)
|
||||
{
|
||||
astrobwt_dero_v2(input, static_cast<uint32_t>(size), ctx[0]->memory, output);
|
||||
}
|
||||
|
|
|
@ -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<Algorithm::Id ALGO>
|
||||
|
@ -40,5 +41,7 @@ void single_hash(const uint8_t* input, size_t size, uint8_t* output, cryptonight
|
|||
template<>
|
||||
void single_hash<Algorithm::ASTROBWT_DERO>(const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx** ctx, uint64_t);
|
||||
|
||||
template<>
|
||||
void single_hash<Algorithm::ASTROBWT_DERO_2>(const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx** ctx, uint64_t);
|
||||
|
||||
}} // namespace xmrig::astrobwt
|
||||
|
|
208
src/crypto/astrobwt/sort_indices2.cpp
Normal file
208
src/crypto/astrobwt/sort_indices2.cpp
Normal file
|
@ -0,0 +1,208 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018 Lee Clagett <https://github.com/vtnerd>
|
||||
* Copyright (c) 2018-2019 tevador <tevador@gmail.com>
|
||||
* Copyright (c) 2000 Transmeta Corporation <https://github.com/intel/msr-tools>
|
||||
* Copyright (c) 2004-2008 H. Peter Anvin <https://github.com/intel/msr-tools>
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "crypto/astrobwt/sort_indices2.h"
|
||||
#include "base/tools/bswap_64.h"
|
||||
#include <cstring>
|
||||
|
||||
|
||||
#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);
|
||||
}
|
26
src/crypto/astrobwt/sort_indices2.h
Normal file
26
src/crypto/astrobwt/sort_indices2.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* XMRig
|
||||
* Copyright (c) 2018 Lee Clagett <https://github.com/vtnerd>
|
||||
* Copyright (c) 2018-2019 tevador <tevador@gmail.com>
|
||||
* Copyright (c) 2000 Transmeta Corporation <https://github.com/intel/msr-tools>
|
||||
* Copyright (c) 2004-2008 H. Peter Anvin <https://github.com/intel/msr-tools>
|
||||
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void sort_indices_astrobwt_v2(uint32_t N, const uint8_t* v, uint32_t* indices, uint32_t* tmp_indices);
|
|
@ -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<Algorithm::ASTROBWT_DERO>;
|
||||
m_map[Algorithm::ASTROBWT_DERO]->data[AV_SINGLE_SOFT][Assembly::NONE] = astrobwt::single_hash<Algorithm::ASTROBWT_DERO>;
|
||||
|
||||
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<Algorithm::ASTROBWT_DERO_2>;
|
||||
m_map[Algorithm::ASTROBWT_DERO_2]->data[AV_SINGLE_SOFT][Assembly::NONE] = astrobwt::single_hash<Algorithm::ASTROBWT_DERO_2>;
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_ALGO_GHOSTRIDER
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
Loading…
Reference in a new issue