Compare commits

...

12 Commits
v6.24.0 ... dev

Author SHA1 Message Date
xmrig
dabbe08016 Merge pull request #598 from SChernykh/dev
Sync changes with XMRig
2026-02-02 18:24:17 +07:00
SChernykh
cd7328b4a8 Sync changes with XMRig 2026-02-02 12:05:44 +01:00
XMRig
9a95a5fe92 Merge branch 'pr597' into dev 2026-01-21 21:51:56 +07:00
XMRig
ccd5e46f95 Merge branch 'fix-keepalive-timer' of https://github.com/HashVault/vltrig-proxy into pr597 2026-01-21 21:51:20 +07:00
HashVault
ea08c9f6c2 Fix keepalive timer logic
- Reset timer on send instead of receive (pool needs to know we're alive)
- Remove timer disable after first ping to enable continuous keepalives

The previous implementation only sent one keepalive ping because
m_keepAlive was set to 0 after ping(), disabling the timer. Also,
resetting the timer on receive doesn't make sense - the pool needs to
know the client is still alive, which requires activity from the client
side, not just receiving data.
2026-01-20 14:31:49 +03:00
XMRig
9353384e31 Replace uv_now to Chrono::steadyMSecs. 2025-10-26 19:45:34 +07:00
XMRig
ac11b81c62 Fixed mishandled timeouts. 2025-10-25 12:13:14 +07:00
xmrig
9091479130 Merge pull request #590 from SChernykh/dev
Solo mining: added support for FCMP++ hardfork
2025-10-06 07:47:00 +07:00
SChernykh
c7c9cf229d Solo mining: added support for FCMP++ hardfork 2025-10-06 02:30:16 +02:00
XMRig
8df03ed9c3 Added OpenBSD recognition and improved LibreSSL support. 2025-06-29 11:41:33 +07:00
XMRig
007d2478ca v6.24.1-dev 2025-06-23 08:36:29 +07:00
XMRig
5cf5cdaed0 Merge branch 'master' into dev 2025-06-23 08:35:49 +07:00
26 changed files with 223 additions and 123 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
/build
/CMakeLists.txt.user
.vscode

View File

@@ -137,10 +137,12 @@ else()
src/App_unix.cpp
)
if (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
set(EXTRA_LIBS pthread)
else()
if (XMRIG_OS_ANDROID)
set(EXTRA_LIBS pthread rt dl log)
elseif (XMRIG_OS_LINUX)
set(EXTRA_LIBS pthread rt dl)
elseif (XMRIG_OS_FREEBSD)
set(EXTRA_LIBS kvm pthread)
endif()
endif()

View File

@@ -17,6 +17,8 @@ else()
set(XMRIG_OS_LINUX ON)
elseif(CMAKE_SYSTEM_NAME STREQUAL FreeBSD OR CMAKE_SYSTEM_NAME STREQUAL DragonFly)
set(XMRIG_OS_FREEBSD ON)
elseif(CMAKE_SYSTEM_NAME STREQUAL OpenBSD)
set(XMRIG_OS_OPENBSD ON)
endif()
endif()
@@ -43,6 +45,8 @@ elseif(XMRIG_OS_UNIX)
add_definitions(-DXMRIG_OS_LINUX)
elseif (XMRIG_OS_FREEBSD)
add_definitions(-DXMRIG_OS_FREEBSD)
elseif (XMRIG_OS_OPENBSD)
add_definitions(-DXMRIG_OS_OPENBSD)
endif()
endif()

View File

@@ -77,6 +77,7 @@ const char *Algorithm::kCN_UPX2 = "cn/upx2";
#ifdef XMRIG_ALGO_RANDOMX
const char *Algorithm::kRX = "rx";
const char *Algorithm::kRX_0 = "rx/0";
const char *Algorithm::kRX_V2 = "rx/2";
const char *Algorithm::kRX_WOW = "rx/wow";
const char *Algorithm::kRX_ARQ = "rx/arq";
const char *Algorithm::kRX_GRAFT = "rx/graft";
@@ -143,6 +144,7 @@ static const std::map<uint32_t, const char *> kAlgorithmNames = {
# ifdef XMRIG_ALGO_RANDOMX
ALGO_NAME(RX_0),
ALGO_NAME(RX_V2),
ALGO_NAME(RX_WOW),
ALGO_NAME(RX_ARQ),
ALGO_NAME(RX_GRAFT),
@@ -253,6 +255,8 @@ static const std::map<const char *, Algorithm::Id, aliasCompare> kAlgorithmAlias
ALGO_ALIAS(RX_0, "rx/test"),
ALGO_ALIAS(RX_0, "randomx"),
ALGO_ALIAS(RX_0, "rx"),
ALGO_ALIAS_AUTO(RX_V2), ALGO_ALIAS(RX_V2, "randomx/v2"),
ALGO_ALIAS(RX_V2, "rx/v2"),
ALGO_ALIAS_AUTO(RX_WOW), ALGO_ALIAS(RX_WOW, "randomx/wow"),
ALGO_ALIAS(RX_WOW, "randomwow"),
ALGO_ALIAS_AUTO(RX_ARQ), ALGO_ALIAS(RX_ARQ, "randomx/arq"),
@@ -350,7 +354,7 @@ std::vector<xmrig::Algorithm> xmrig::Algorithm::all(const std::function<bool(con
CN_HEAVY_0, CN_HEAVY_TUBE, CN_HEAVY_XHV,
CN_PICO_0, CN_PICO_TLO,
CN_UPX2,
RX_0, RX_WOW, RX_ARQ, RX_GRAFT, RX_SFX, RX_YADA,
RX_0, RX_V2, RX_WOW, RX_ARQ, RX_GRAFT, RX_SFX, RX_YADA,
AR2_CHUKWA, AR2_CHUKWA_V2, AR2_WRKZ,
KAWPOW_RVN,
GHOSTRIDER_RTM

View File

@@ -73,6 +73,7 @@ public:
CN_GR_5 = 0x63120105, // "cn/turtle-lite" GhostRider
GHOSTRIDER_RTM = 0x6c150000, // "ghostrider" GhostRider
RX_0 = 0x72151200, // "rx/0" RandomX (reference configuration).
RX_V2 = 0x72151202, // "rx/2" RandomX (Monero v2).
RX_WOW = 0x72141177, // "rx/wow" RandomWOW (Wownero).
RX_ARQ = 0x72121061, // "rx/arq" RandomARQ (Arqma).
RX_GRAFT = 0x72151267, // "rx/graft" RandomGRAFT (Graft).
@@ -139,6 +140,7 @@ public:
# ifdef XMRIG_ALGO_RANDOMX
static const char *kRX;
static const char *kRX_0;
static const char* kRX_V2;
static const char *kRX_WOW;
static const char *kRX_ARQ;
static const char *kRX_GRAFT;

View File

@@ -48,7 +48,7 @@
#define KECCAK_ROUNDS 24
/* *************************** Public Inteface ************************ */
/* *************************** Public Interface ************************ */
/* For Init or Reset call these: */
sha3_return_t

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 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
@@ -71,11 +71,11 @@ char *xmrig::Platform::createUserAgent()
#ifndef XMRIG_FEATURE_HWLOC
#ifdef __DragonFly__
#if defined(__DragonFly__) || defined(XMRIG_OS_OPENBSD) || defined(XMRIG_OS_HAIKU)
bool xmrig::Platform::setThreadAffinity(uint64_t cpu_id)
{
return true;
return false;
}
#else

View File

@@ -81,7 +81,7 @@ xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
BaseClient(id, listener),
m_agent(agent),
m_sendBuf(1024),
m_tempBuf(256)
m_tempBuf(320)
{
m_reader.setListener(this);
m_key = m_storage.add(this);
@@ -199,6 +199,7 @@ int64_t xmrig::Client::submit(const JobResult &result)
char *nonce = m_tempBuf.data();
char *data = m_tempBuf.data() + 16;
char *signature = m_tempBuf.data() + 88;
char *commitment = m_tempBuf.data() + 224;
Cvt::toHex(nonce, sizeof(uint32_t) * 2 + 1, reinterpret_cast<const uint8_t *>(&result.nonce), sizeof(uint32_t));
Cvt::toHex(data, 65, result.result(), 32);
@@ -206,6 +207,10 @@ int64_t xmrig::Client::submit(const JobResult &result)
if (result.minerSignature()) {
Cvt::toHex(signature, 129, result.minerSignature(), 64);
}
if (result.commitment()) {
Cvt::toHex(commitment, 65, result.commitment(), 32);
}
# endif
Document doc(kObjectType);
@@ -227,6 +232,16 @@ int64_t xmrig::Client::submit(const JobResult &result)
}
# endif
# ifndef XMRIG_PROXY_PROJECT
if (result.commitment()) {
params.AddMember("commitment", StringRef(commitment), allocator);
}
# else
if (result.commitment) {
params.AddMember("commitment", StringRef(result.commitment), allocator);
}
# endif
if (has<EXT_ALGO>() && result.algorithm.isValid()) {
params.AddMember("algo", StringRef(result.algorithm.name()), allocator);
}
@@ -554,6 +569,7 @@ int64_t xmrig::Client::send(size_t size)
}
m_expire = Chrono::steadyMSecs() + kResponseTimeout;
startTimeout();
return m_sequence++;
}
@@ -661,8 +677,6 @@ void xmrig::Client::onClose()
void xmrig::Client::parse(char *line, size_t len)
{
startTimeout();
LOG_DEBUG("[%s] received (%d bytes): \"%.*s\"", url(), len, static_cast<int>(len), line);
if (len < 22 || line[0] != '{') {
@@ -857,8 +871,6 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co
void xmrig::Client::ping()
{
send(snprintf(m_sendBuf.data(), m_sendBuf.size(), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId.data()));
m_keepAlive = 0;
}

View File

@@ -410,6 +410,7 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
m_blocktemplate.offset(BlockTemplate::TX_EXTRA_NONCE_OFFSET) - k,
m_blocktemplate.txExtraNonce().size(),
m_blocktemplate.minerTxMerkleTreeBranch(),
m_blocktemplate.minerTxMerkleTreePath(),
m_blocktemplate.outputType() == 3
);
# endif

View File

@@ -269,6 +269,7 @@ void xmrig::Job::copy(const Job &other)
m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = other.m_minerTxMerkleTreeBranch;
m_minerTxMerkleTreePath = other.m_minerTxMerkleTreePath;
m_hasViewTag = other.m_hasViewTag;
# else
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
@@ -325,6 +326,7 @@ void xmrig::Job::move(Job &&other)
m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = std::move(other.m_minerTxMerkleTreeBranch);
m_minerTxMerkleTreePath = other.m_minerTxMerkleTreePath;
m_hasViewTag = other.m_hasViewTag;
# else
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
@@ -349,7 +351,7 @@ void xmrig::Job::setSpendSecretKey(const uint8_t *key)
}
void xmrig::Job::setMinerTx(const uint8_t *begin, const uint8_t *end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer &minerTxMerkleTreeBranch, bool hasViewTag)
void xmrig::Job::setMinerTx(const uint8_t *begin, const uint8_t *end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer &minerTxMerkleTreeBranch, uint32_t minerTxMerkleTreePath, bool hasViewTag)
{
m_minerTxPrefix.assign(begin, end);
m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset;
@@ -357,6 +359,7 @@ void xmrig::Job::setMinerTx(const uint8_t *begin, const uint8_t *end, size_t min
m_minerTxExtraNonceOffset = minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = minerTxMerkleTreeBranch;
m_minerTxMerkleTreePath = minerTxMerkleTreePath;
m_hasViewTag = hasViewTag;
}
@@ -401,7 +404,7 @@ void xmrig::Job::generateHashingBlob(String &blob) const
{
uint8_t root_hash[32];
const uint8_t* p = m_minerTxPrefix.data();
BlockTemplate::calculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, root_hash);
BlockTemplate::calculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, m_minerTxMerkleTreePath, root_hash);
uint64_t root_hash_offset = nonceOffset() + nonceSize();

View File

@@ -121,7 +121,7 @@ public:
inline bool hasViewTag() const { return m_hasViewTag; }
void setSpendSecretKey(const uint8_t* key);
void setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer& minerTxMerkleTreeBranch, bool hasViewTag);
void setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer& minerTxMerkleTreeBranch, uint32_t minerTxMerkleTreePath, bool hasViewTag);
void setViewTagInMinerTx(uint8_t view_tag);
void setExtraNonceInMinerTx(uint32_t extra_nonce);
void generateSignatureData(String& signatureData, uint8_t& view_tag) const;
@@ -179,6 +179,7 @@ private:
size_t m_minerTxExtraNonceOffset = 0;
size_t m_minerTxExtraNonceSize = 0;
Buffer m_minerTxMerkleTreeBranch;
uint32_t m_minerTxMerkleTreePath = 0;
bool m_hasViewTag = false;
# else
// Miner signatures

View File

@@ -1,7 +1,7 @@
/* XMRig
* Copyright (c) 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2025 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
@@ -45,7 +45,7 @@ namespace xmrig {
// https://wiki.openssl.org/index.php/Diffie-Hellman_parameters
#if OPENSSL_VERSION_NUMBER < 0x30000000L || defined(LIBRESSL_VERSION_NUMBER)
#if OPENSSL_VERSION_NUMBER < 0x30000000L || (defined(LIBRESSL_VERSION_NUMBER) && !defined(LIBRESSL_HAS_TLS1_3))
static DH *get_dh2048()
{
static unsigned char dhp_2048[] = {
@@ -152,7 +152,7 @@ bool xmrig::TlsContext::load(const TlsConfig &config)
SSL_CTX_set_options(m_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
SSL_CTX_set_options(m_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
# if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(LIBRESSL_VERSION_NUMBER)
# if OPENSSL_VERSION_NUMBER >= 0x1010100fL || defined(LIBRESSL_HAS_TLS1_3)
SSL_CTX_set_max_early_data(m_ctx, 0);
# endif
@@ -180,7 +180,7 @@ bool xmrig::TlsContext::setCipherSuites(const char *ciphersuites)
return true;
}
# if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(LIBRESSL_VERSION_NUMBER)
# if OPENSSL_VERSION_NUMBER >= 0x1010100fL || defined(LIBRESSL_HAS_TLS1_3)
if (SSL_CTX_set_ciphersuites(m_ctx, ciphersuites) == 1) {
return true;
}
@@ -194,7 +194,7 @@ bool xmrig::TlsContext::setCipherSuites(const char *ciphersuites)
bool xmrig::TlsContext::setDH(const char *dhparam)
{
# if OPENSSL_VERSION_NUMBER < 0x30000000L || defined(LIBRESSL_VERSION_NUMBER)
# if OPENSSL_VERSION_NUMBER < 0x30000000L || (defined(LIBRESSL_VERSION_NUMBER) && !defined(LIBRESSL_HAS_TLS1_3))
DH *dh = nullptr;
if (dhparam != nullptr) {

View File

@@ -48,69 +48,98 @@ void xmrig::BlockTemplate::calculateMinerTxHash(const uint8_t *prefix_begin, con
}
void xmrig::BlockTemplate::calculateRootHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, const Buffer &miner_tx_merkle_tree_branch, uint8_t *root_hash)
void xmrig::BlockTemplate::calculateRootHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, const Buffer &miner_tx_merkle_tree_branch, uint32_t miner_tx_merkle_tree_path, uint8_t *root_hash)
{
calculateMinerTxHash(prefix_begin, prefix_end, root_hash);
for (size_t i = 0; i < miner_tx_merkle_tree_branch.size(); i += kHashSize) {
const size_t depth = miner_tx_merkle_tree_branch.size() / kHashSize;
for (size_t d = 0; d < depth; ++d) {
uint8_t h[kHashSize * 2];
memcpy(h, root_hash, kHashSize);
memcpy(h + kHashSize, miner_tx_merkle_tree_branch.data() + i, kHashSize);
const uint32_t t = (miner_tx_merkle_tree_path >> (depth - d - 1)) & 1;
memcpy(h + kHashSize * t, root_hash, kHashSize);
memcpy(h + kHashSize * (t ^ 1), miner_tx_merkle_tree_branch.data() + d * kHashSize, kHashSize);
keccak(h, kHashSize * 2, root_hash, kHashSize);
}
}
void xmrig::BlockTemplate::calculateMerkleTreeHash()
void xmrig::BlockTemplate::calculateMerkleTreeHash(uint32_t index)
{
m_minerTxMerkleTreeBranch.clear();
m_minerTxMerkleTreePath = 0;
const uint64_t count = m_numHashes + 1;
const size_t count = m_hashes.size() / kHashSize;
const uint8_t *h = m_hashes.data();
if (count == 1) {
if (count == 1) {
memcpy(m_rootHash, h, kHashSize);
}
else if (count == 2) {
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize, h + kHashSize * 2);
}
else if (count == 2) {
keccak(h, kHashSize * 2, m_rootHash, kHashSize);
}
else {
size_t i = 0;
size_t j = 0;
size_t cnt = 0;
for (i = 0, cnt = 1; cnt <= count; ++i, cnt <<= 1) {}
m_minerTxMerkleTreeBranch.reserve(1);
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize * (index ^ 1), h + kHashSize * ((index ^ 1) + 1));
m_minerTxMerkleTreePath = static_cast<uint32_t>(index);
}
else {
uint8_t h2[kHashSize];
memcpy(h2, h + kHashSize * index, kHashSize);
cnt >>= 1;
size_t cnt = 1, proof_max_size = 0;
do {
cnt <<= 1;
++proof_max_size;
} while (cnt <= count);
cnt >>= 1;
m_minerTxMerkleTreeBranch.reserve(kHashSize * (i - 1));
m_minerTxMerkleTreeBranch.reserve(proof_max_size);
Buffer ints(cnt * kHashSize);
memcpy(ints.data(), h, (cnt * 2 - count) * kHashSize);
for (i = cnt * 2 - count, j = cnt * 2 - count; j < cnt; i += 2, ++j) {
if (i == 0) {
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize, h + kHashSize * 2);
}
keccak(h + i * kHashSize, kHashSize * 2, ints.data() + j * kHashSize, kHashSize);
}
const size_t k = cnt * 2 - count;
memcpy(ints.data(), h, k * kHashSize);
while (cnt > 2) {
cnt >>= 1;
for (i = 0, j = 0; j < cnt; i += 2, ++j) {
if (i == 0) {
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), ints.data() + kHashSize, ints.data() + kHashSize * 2);
}
keccak(ints.data() + i * kHashSize, kHashSize * 2, ints.data() + j * kHashSize, kHashSize);
}
}
for (size_t i = k, j = k; j < cnt; i += 2, ++j) {
keccak(h + i * kHashSize, kHashSize * 2, ints.data() + j * kHashSize, kHashSize);
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), ints.data() + kHashSize, ints.data() + kHashSize * 2);
keccak(ints.data(), kHashSize * 2, m_rootHash, kHashSize);
}
if (memcmp(h + i * kHashSize, h2, kHashSize) == 0) {
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize * (i + 1), h + kHashSize * (i + 2));
memcpy(h2, ints.data() + j * kHashSize, kHashSize);
}
else if (memcmp(h + (i + 1) * kHashSize, h2, kHashSize) == 0) {
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize * i, h + kHashSize * (i + 1));
memcpy(h2, ints.data() + j * kHashSize, kHashSize);
m_minerTxMerkleTreePath = 1;
}
}
while (cnt >= 2) {
cnt >>= 1;
for (size_t i = 0, j = 0; j < cnt; i += 2, ++j) {
uint8_t tmp[kHashSize];
keccak(ints.data() + i * kHashSize, kHashSize * 2, tmp, kHashSize);
if (memcmp(ints.data() + i * kHashSize, h2, kHashSize) == 0) {
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), ints.data() + kHashSize * (i + 1), ints.data() + kHashSize * (i + 2));
memcpy(h2, tmp, kHashSize);
m_minerTxMerkleTreePath <<= 1;
}
else if (memcmp(ints.data() + (i + 1) * kHashSize, h2, kHashSize) == 0) {
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), ints.data() + kHashSize * i, ints.data() + kHashSize * (i + 1));
memcpy(h2, tmp, kHashSize);
m_minerTxMerkleTreePath = (m_minerTxMerkleTreePath << 1) | 1;
}
memcpy(ints.data() + j * kHashSize, tmp, kHashSize);
}
}
memcpy(m_rootHash, ints.data(), kHashSize);
}
}
@@ -241,8 +270,13 @@ bool xmrig::BlockTemplate::parse(bool hashes)
ar(m_amount);
ar(m_outputType);
// output type must be txout_to_key (2) or txout_to_tagged_key (3)
if ((m_outputType != 2) && (m_outputType != 3)) {
const bool is_fcmp_pp = (m_coin == Coin::MONERO) && (m_version.first >= 17);
// output type must be txout_to_key (2) or txout_to_tagged_key (3) for versions < 17, and txout_to_carrot_v1 (0) for version FCMP++
if (is_fcmp_pp && (m_outputType == 0)) {
// all good
}
else if ((m_outputType != 2) && (m_outputType != 3)) {
return false;
}
@@ -250,6 +284,11 @@ bool xmrig::BlockTemplate::parse(bool hashes)
ar(m_ephPublicKey, kKeySize);
if (is_fcmp_pp) {
ar(m_carrotViewTag);
ar(m_janusAnchor);
}
if (m_coin == Coin::ZEPHYR) {
if (m_outputType != 2) {
return false;
@@ -365,16 +404,42 @@ bool xmrig::BlockTemplate::parse(bool hashes)
ar(m_numHashes);
if (hashes) {
m_hashes.resize((m_numHashes + 1) * kHashSize);
calculateMinerTxHash(blob(MINER_TX_PREFIX_OFFSET), blob(MINER_TX_PREFIX_END_OFFSET), m_hashes.data());
// FCMP++ layout:
//
// index 0 fcmp_pp_n_tree_layers + 31 zero bytes
// index 1 fcmp_pp_tree_root
// index 2 coinbase transaction hash
// index 3+ other transaction hashes
//
// pre-FCMP++ layout:
//
// index 0 coinbase transaction hash
// index 1+ other transaction hashes
//
const uint32_t coinbase_tx_index = is_fcmp_pp ? 2 : 0;
m_hashes.clear();
m_hashes.resize((coinbase_tx_index + m_numHashes + 1) * kHashSize);
uint8_t* data = m_hashes.data() + coinbase_tx_index * kHashSize;
calculateMinerTxHash(blob(MINER_TX_PREFIX_OFFSET), blob(MINER_TX_PREFIX_END_OFFSET), data);
for (uint64_t i = 1; i <= m_numHashes; ++i) {
Span h;
ar(h, kHashSize);
memcpy(m_hashes.data() + i * kHashSize, h.data(), kHashSize);
memcpy(data + i * kHashSize, h.data(), kHashSize);
}
calculateMerkleTreeHash();
if (is_fcmp_pp) {
ar(m_FCMPTreeLayers);
ar(m_FCMPTreeRoot);
m_hashes[0] = m_FCMPTreeLayers;
memcpy(m_hashes.data() + kHashSize, m_FCMPTreeRoot, kHashSize);
}
calculateMerkleTreeHash(coinbase_tx_index);
}
return true;

View File

@@ -93,6 +93,7 @@ public:
inline uint64_t numHashes() const { return m_numHashes; }
inline const Buffer &hashes() const { return m_hashes; }
inline const Buffer &minerTxMerkleTreeBranch() const { return m_minerTxMerkleTreeBranch; }
inline uint32_t minerTxMerkleTreePath() const { return m_minerTxMerkleTreePath; }
inline const uint8_t *rootHash() const { return m_rootHash; }
inline Buffer generateHashingBlob() const
@@ -104,13 +105,13 @@ public:
}
static void calculateMinerTxHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, uint8_t *hash);
static void calculateRootHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, const Buffer &miner_tx_merkle_tree_branch, uint8_t *root_hash);
static void calculateRootHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, const Buffer &miner_tx_merkle_tree_branch, uint32_t miner_tx_merkle_tree_path, uint8_t *root_hash);
bool parse(const Buffer &blocktemplate, const Coin &coin, bool hashes = kCalcHashes);
bool parse(const char *blocktemplate, size_t size, const Coin &coin, bool hashes);
bool parse(const rapidjson::Value &blocktemplate, const Coin &coin, bool hashes = kCalcHashes);
bool parse(const String &blocktemplate, const Coin &coin, bool hashes = kCalcHashes);
void calculateMerkleTreeHash();
void calculateMerkleTreeHash(uint32_t index);
void generateHashingBlob(Buffer &out) const;
private:
@@ -147,7 +148,12 @@ private:
uint64_t m_numHashes = 0;
Buffer m_hashes;
Buffer m_minerTxMerkleTreeBranch;
uint32_t m_minerTxMerkleTreePath = 0;
uint8_t m_rootHash[kHashSize]{};
uint8_t m_carrotViewTag[3]{};
uint8_t m_janusAnchor[16]{};
uint8_t m_FCMPTreeLayers = 0;
uint8_t m_FCMPTreeRoot[kHashSize]{};
};

View File

@@ -76,7 +76,7 @@ static inline const std::string &usage()
u += "\nOptions:\n";
u += " -b, --bind=ADDR bind to specified address, example \"0.0.0.0:3333\"\n";
u += " -m, --mode=MODE proxy mode, nicehash (default) or simple\n";
u += " -m, --mode=MODE proxy mode: nicehash (default), simple or extra_nonce\n";
u += " --custom-diff=N override pool diff\n";
u += " --custom-diff-stats calculate stats using custom diff shares instead of pool shares\n";
u += " --reuse-timeout=N timeout in seconds for reuse pool connections in simple mode\n";

View File

@@ -25,12 +25,13 @@
#include <cstdio>
xmrig::JobResult::JobResult(int64_t id, const char *jobId, const char *nonce, const char *result, const xmrig::Algorithm &algorithm, const char* sig, const char* sig_data, uint8_t view_tag, int64_t extra_nonce) :
xmrig::JobResult::JobResult(int64_t id, const char *jobId, const char *nonce, const char *result, const xmrig::Algorithm &algorithm, const char* sig, const char* sig_data, const char* commitment, uint8_t view_tag, int64_t extra_nonce) :
algorithm(algorithm),
nonce(nonce),
result(result),
sig(sig),
sig_data(sig_data),
commitment(commitment),
view_tag(view_tag),
id(id),
extra_nonce(extra_nonce),

View File

@@ -37,7 +37,7 @@ public:
static constexpr uint32_t backend = 0;
JobResult() = default;
JobResult(int64_t id, const char *jobId, const char *nonce, const char *result, const xmrig::Algorithm &algorithm, const char* sig, const char* sig_data, uint8_t view_tag, int64_t extra_nonce);
JobResult(int64_t id, const char *jobId, const char *nonce, const char *result, const xmrig::Algorithm &algorithm, const char* sig, const char* sig_data, const char* commitment, uint8_t view_tag, int64_t extra_nonce);
bool isCompatible(uint8_t fixedByte) const;
bool isValid() const;
@@ -49,6 +49,7 @@ public:
const char *result = nullptr;
const char *sig = nullptr;
const char *sig_data = nullptr;
const char *commitment = nullptr;
const uint8_t view_tag = 0;
const int64_t id = 0;
const int64_t extra_nonce = -1;

View File

@@ -58,7 +58,7 @@ namespace xmrig {
static int64_t nextId = 0;
char Miner::m_sendBuf[16384] = { 0 };
Storage<Miner> Miner::m_storage;
}
} // namespace xmrig
xmrig::Miner::Miner(const TlsContext *ctx, uint16_t port, bool strictTls) :
@@ -67,7 +67,7 @@ xmrig::Miner::Miner(const TlsContext *ctx, uint16_t port, bool strictTls) :
m_tlsCtx(ctx),
m_id(++nextId),
m_localPort(port),
m_expire(Chrono::currentMSecsSinceEpoch() + kLoginTimeout),
m_expire(Chrono::steadyMSecs() + kLoginTimeout),
m_timestamp(Chrono::currentMSecsSinceEpoch())
{
m_reader.setListener(this);
@@ -215,7 +215,7 @@ bool xmrig::Miner::parseRequest(int64_t id, const char *method, const rapidjson:
algorithms.reserve(value.Size());
for (const auto &i : value.GetArray()) {
Algorithm algo(i.GetString());
const Algorithm algo(i.GetString());
if (!algo.isValid()) {
continue;
}
@@ -252,7 +252,7 @@ bool xmrig::Miner::parseRequest(int64_t id, const char *method, const rapidjson:
Algorithm algorithm(Json::getString(params, "algo"));
SubmitEvent *event = SubmitEvent::create(this, id, Json::getString(params, "job_id"), Json::getString(params, "nonce"), Json::getString(params, "result"), algorithm, Json::getString(params, "sig"), m_signatureData, m_viewTag, m_extraNonce);
SubmitEvent *event = SubmitEvent::create(this, id, Json::getString(params, "job_id"), Json::getString(params, "nonce"), Json::getString(params, "result"), algorithm, Json::getString(params, "sig"), m_signatureData, Json::getString(params, "commitment"), m_viewTag, m_extraNonce);
if (!event->request.isValid() || event->request.actualDiff() < diff()) {
event->setError(Error::LowDifficulty);
@@ -324,7 +324,7 @@ bool xmrig::Miner::send(BIO *bio)
void xmrig::Miner::heartbeat()
{
m_expire = Chrono::currentMSecsSinceEpoch() + kSocketTimeout;
m_expire = Chrono::steadyMSecs() + kSocketTimeout;
}

View File

@@ -5,8 +5,8 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2025 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
@@ -25,12 +25,10 @@
#ifndef XMRIG_MINER_H
#define XMRIG_MINER_H
#include <algorithm>
#include <bitset>
#include <uv.h>
#include "3rdparty/rapidjson/fwd.h"
#include "base/kernel/interfaces/ILineListener.h"
#include "base/net/tools/LineReader.h"
@@ -147,7 +145,7 @@ private:
String m_rigId;
String m_user;
String m_signatureData;
uint8_t m_viewTag;
uint8_t m_viewTag = 0;
Tls *m_tls = nullptr;
uint16_t m_localPort;
uint64_t m_customDiff = 0;
@@ -166,6 +164,6 @@ private:
};
} /* namespace xmrig */
} // namespace xmrig
#endif /* XMRIG_MINER_H */
#endif // XMRIG_MINER_H

View File

@@ -5,8 +5,8 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2025 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
@@ -25,8 +25,7 @@
#include <vector>
#include "base/io/log/Log.h"
#include "base/tools/Chrono.h"
#include "base/tools/Handle.h"
#include "proxy/events/CloseEvent.h"
#include "proxy/events/ConnectionEvent.h"
@@ -34,9 +33,9 @@
#include "proxy/Miners.h"
xmrig::Miners::Miners()
xmrig::Miners::Miners() :
m_timer(new uv_timer_t)
{
m_timer = new uv_timer_t;
m_timer->data = this;
uv_timer_init(uv_default_loop(), m_timer);
uv_timer_start(m_timer, [](uv_timer_t *handle) { static_cast<Miners*>(handle->data)->tick(); }, kTickInterval, kTickInterval);
@@ -101,7 +100,7 @@ void xmrig::Miners::remove(Miner *miner)
void xmrig::Miners::tick()
{
const uint64_t now = uv_now(uv_default_loop());
const uint64_t now = Chrono::steadyMSecs();
std::vector<Miner*> expired;
for (auto const &kv : m_miners) {
@@ -114,7 +113,7 @@ void xmrig::Miners::tick()
return;
}
for (auto miner : expired) {
for (auto *miner : expired) {
miner->close();
}
}

View File

@@ -37,9 +37,9 @@ namespace xmrig {
class SubmitEvent : public MinerEvent
{
public:
static inline SubmitEvent *create(Miner *miner, int64_t id, const char *jobId, const char *nonce, const char *result, const Algorithm &algorithm, const char* sig, const char* sig_data, uint8_t view_tag, int64_t extra_nonce)
static inline SubmitEvent *create(Miner *miner, int64_t id, const char *jobId, const char *nonce, const char *result, const Algorithm &algorithm, const char* sig, const char* sig_data, const char* commitment, uint8_t view_tag, int64_t extra_nonce)
{
return new (m_buf) SubmitEvent(miner, id, jobId, nonce, result, algorithm, sig, sig_data, view_tag, extra_nonce);
return new (m_buf) SubmitEvent(miner, id, jobId, nonce, result, algorithm, sig, sig_data, commitment, view_tag, extra_nonce);
}
@@ -54,9 +54,9 @@ public:
protected:
inline SubmitEvent(Miner *miner, int64_t id, const char *jobId, const char *nonce, const char *result, const Algorithm &algorithm, const char* sig, const char* sig_data, uint8_t view_tag, int64_t extra_nonce)
inline SubmitEvent(Miner *miner, int64_t id, const char *jobId, const char *nonce, const char *result, const Algorithm &algorithm, const char* sig, const char* sig_data, const char* commitment, uint8_t view_tag, int64_t extra_nonce)
: MinerEvent(SubmitType, miner),
request(id, jobId, nonce, result, algorithm, sig, sig_data, view_tag, extra_nonce),
request(id, jobId, nonce, result, algorithm, sig, sig_data, commitment, view_tag, extra_nonce),
m_error(Error::NoError)
{}

View File

@@ -5,8 +5,8 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2025 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
@@ -24,6 +24,7 @@
#include "proxy/splitters/extra_nonce/ExtraNonceSplitter.h"
#include "base/io/log/Log.h"
#include "base/tools/Chrono.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "proxy/Counters.h"
@@ -95,8 +96,7 @@ void xmrig::ExtraNonceSplitter::printConnections()
void xmrig::ExtraNonceSplitter::tick(uint64_t ticks)
{
const uint64_t now = uv_now(uv_default_loop());
m_upstream->tick(ticks, now);
m_upstream->tick(ticks, Chrono::steadyMSecs());
}

View File

@@ -5,8 +5,8 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2025 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
@@ -24,6 +24,7 @@
#include "proxy/splitters/nicehash/NonceSplitter.h"
#include "base/io/log/Log.h"
#include "base/tools/Chrono.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "proxy/Counters.h"
@@ -34,7 +35,6 @@
#include "proxy/splitters/nicehash/NonceMapper.h"
#include "Summary.h"
#include <cinttypes>
@@ -77,7 +77,7 @@ xmrig::Upstreams xmrig::NonceSplitter::upstreams() const
void xmrig::NonceSplitter::connect()
{
auto upstream = new NonceMapper(m_upstreams.size(), m_controller);
auto *upstream = new NonceMapper(m_upstreams.size(), m_controller);
m_upstreams.push_back(upstream);
upstream->start();
@@ -113,7 +113,7 @@ void xmrig::NonceSplitter::printConnections()
void xmrig::NonceSplitter::tick(uint64_t ticks)
{
const uint64_t now = uv_now(uv_default_loop());
const uint64_t now = Chrono::steadyMSecs();
for (NonceMapper *mapper : m_upstreams) {
mapper->tick(ticks, now);

View File

@@ -5,8 +5,8 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2025 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
@@ -22,10 +22,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <inttypes.h>
#include "proxy/splitters/simple/SimpleSplitter.h"
#include "base/io/log/Log.h"
#include "base/tools/Chrono.h"
#include "core/config/Config.h"
#include "core/Controller.h"
#include "proxy/Counters.h"
@@ -34,16 +33,16 @@
#include "proxy/events/SubmitEvent.h"
#include "proxy/Miner.h"
#include "proxy/splitters/simple/SimpleMapper.h"
#include "proxy/splitters/simple/SimpleSplitter.h"
#include "Summary.h"
#include <cinttypes>
#define LABEL(x) " \x1B[01;30m" x ":\x1B[0m "
xmrig::SimpleSplitter::SimpleSplitter(xmrig::Controller *controller) : Splitter(controller),
m_reuseTimeout(static_cast<uint64_t>(controller->config()->reuseTimeout())),
m_sequence(0)
m_reuseTimeout(static_cast<uint64_t>(controller->config()->reuseTimeout()))
{
}
@@ -98,7 +97,7 @@ void xmrig::SimpleSplitter::printConnections()
void xmrig::SimpleSplitter::tick(uint64_t ticks)
{
const uint64_t now = uv_now(uv_default_loop());
const uint64_t now = Chrono::steadyMSecs();
for (SimpleMapper *mapper : m_released) {
delete mapper;

View File

@@ -5,8 +5,8 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2025 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2025 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
@@ -25,9 +25,8 @@
#ifndef XMRIG_SIMPLESPLITTER_H
#define XMRIG_SIMPLESPLITTER_H
#include <cstdint>
#include <map>
#include <stdint.h>
#include <vector>
@@ -76,12 +75,12 @@ private:
std::map<uint64_t, SimpleMapper *> m_idles;
std::map<uint64_t, SimpleMapper *> m_upstreams;
std::vector<SimpleMapper *> m_released;
uint64_t m_reuseTimeout;
uint64_t m_sequence;
uint64_t m_reuseTimeout = 0;
uint64_t m_sequence = 0;
};
} /* namespace xmrig */
} // namespace xmrig
#endif /* XMRIG_SIMPLESPLITTER_H */
#endif // XMRIG_SIMPLESPLITTER_H

View File

@@ -22,7 +22,7 @@
#define APP_ID "xmrig-proxy"
#define APP_NAME "xmrig-proxy"
#define APP_DESC "XMRig Stratum proxy"
#define APP_VERSION "6.24.0"
#define APP_VERSION "6.24.1-dev"
#define APP_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2025 xmrig.com"
@@ -30,7 +30,7 @@
#define APP_VER_MAJOR 6
#define APP_VER_MINOR 24
#define APP_VER_PATCH 0
#define APP_VER_PATCH 1
#ifdef _MSC_VER
# if (_MSC_VER >= 1930)
@@ -64,6 +64,8 @@
# define APP_OS "Linux"
#elif defined XMRIG_OS_FREEBSD
# define APP_OS "FreeBSD"
#elif defined XMRIG_OS_OPENBSD
# define APP_OS "OpenBSD"
#else
# define APP_OS "Unknown OS"
#endif