From 7177b42903af6856ff06bee9be2850d6a92dcb96 Mon Sep 17 00:00:00 2001 From: XMRig <support@xmrig.com> Date: Sat, 3 Jul 2021 16:00:30 +0700 Subject: [PATCH 1/8] v6.13.2-dev --- src/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.h b/src/version.h index 4d7714fdd..5dfc7b2b7 100644 --- a/src/version.h +++ b/src/version.h @@ -28,7 +28,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig miner" -#define APP_VERSION "6.13.1" +#define APP_VERSION "6.13.2-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2021 xmrig.com" @@ -36,7 +36,7 @@ #define APP_VER_MAJOR 6 #define APP_VER_MINOR 13 -#define APP_VER_PATCH 1 +#define APP_VER_PATCH 2 #ifdef _MSC_VER # if (_MSC_VER >= 1920) From 3f2dfa42794fc7a097fa55d426bdfa4f0dc22fdd Mon Sep 17 00:00:00 2001 From: XMRig <support@xmrig.com> Date: Mon, 5 Jul 2021 02:31:29 +0700 Subject: [PATCH 2/8] Sync with proxy. --- src/base/net/stratum/Client.cpp | 15 ++++----- src/base/net/stratum/Client.h | 4 +-- src/base/net/stratum/Job.cpp | 60 ++++++++++++++++++++++----------- src/base/net/stratum/Job.h | 23 +++++++------ 4 files changed, 63 insertions(+), 39 deletions(-) diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 1871b6df0..95e1d8d05 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -6,8 +6,8 @@ * Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2019 jtgrassie <https://github.com/jtgrassie> - * Copyright 2018-2020 SChernykh <https://github.com/SChernykh> - * Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com> + * Copyright 2018-2021 SChernykh <https://github.com/SChernykh> + * Copyright 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 @@ -225,6 +225,10 @@ int64_t xmrig::Client::submit(const JobResult &result) if (result.minerSignature()) { params.AddMember("sig", StringRef(signature), allocator); } +# else + if (result.sig) { + params.AddMember("sig", StringRef(result.sig), allocator); + } # endif if (has<EXT_ALGO>() && result.algorithm.isValid()) { @@ -440,12 +444,7 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) return false; } -# ifndef XMRIG_PROXY_PROJECT - uint8_t signatureKeyBuf[32 * 2]; - if (Cvt::fromHex(signatureKeyBuf, sizeof(signatureKeyBuf), Json::getValue(params, "sig_key"))) { - job.setEphemeralKeys(signatureKeyBuf, signatureKeyBuf + 32); - } -# endif + job.setSigKey(Json::getString(params, "sig_key")); m_job.setClientId(m_rpcId); diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index fdaac9f15..d9164b8a3 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -6,8 +6,8 @@ * Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2019 jtgrassie <https://github.com/jtgrassie> - * Copyright 2018-2020 SChernykh <https://github.com/SChernykh> - * Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com> + * Copyright 2018-2021 SChernykh <https://github.com/SChernykh> + * Copyright 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 diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index c92f6f015..5e0c0f489 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -7,8 +7,8 @@ * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2018 Lee Clagett <https://github.com/vtnerd> * Copyright 2019 Howard Chu <https://github.com/hyc> - * Copyright 2018-2020 SChernykh <https://github.com/SChernykh> - * Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com> + * Copyright 2018-2021 SChernykh <https://github.com/SChernykh> + * Copyright 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 @@ -144,6 +144,25 @@ void xmrig::Job::setDiff(uint64_t diff) } +void xmrig::Job::setSigKey(const char *sig_key) +{ + constexpr const size_t size = 64; + + if (!sig_key || strlen(sig_key) != size * 2) { + return; + } + +# ifndef XMRIG_PROXY_PROJECT + const auto buf = Cvt::fromHex(sig_key, size * 2); + if (buf.size() == size) { + setEphemeralKeys(buf.data(), buf.data() + 32); + } +# else + m_rawSigKey = sig_key; +# endif +} + + void xmrig::Job::copy(const Job &other) { m_algorithm = other.m_algorithm; @@ -164,6 +183,7 @@ void xmrig::Job::copy(const Job &other) # ifdef XMRIG_PROXY_PROJECT m_rawSeedHash = other.m_rawSeedHash; + m_rawSigKey = other.m_rawSigKey; memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob)); memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget)); @@ -215,6 +235,7 @@ void xmrig::Job::move(Job &&other) # ifdef XMRIG_PROXY_PROJECT m_rawSeedHash = std::move(other.m_rawSeedHash); + m_rawSigKey = std::move(other.m_rawSigKey); memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob)); memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget)); @@ -229,10 +250,11 @@ void xmrig::Job::move(Job &&other) memcpy(m_viewSecretKey, other.m_viewSecretKey, sizeof(m_viewSecretKey)); memcpy(m_spendPublicKey, other.m_spendPublicKey, sizeof(m_spendPublicKey)); memcpy(m_viewPublicKey, other.m_viewPublicKey, sizeof(m_viewPublicKey)); - m_minerTxPrefix = std::move(other.m_minerTxPrefix); - m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset; - m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset; - m_minerTxMerkleTreeBranch = std::move(other.m_minerTxMerkleTreeBranch); + + m_minerTxPrefix = std::move(other.m_minerTxPrefix); + m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset; + m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset; + m_minerTxMerkleTreeBranch = std::move(other.m_minerTxMerkleTreeBranch); # else memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey)); memcpy(m_ephSecretKey, other.m_ephSecretKey, sizeof(m_ephSecretKey)); @@ -245,26 +267,27 @@ void xmrig::Job::move(Job &&other) #ifdef XMRIG_PROXY_PROJECT -void xmrig::Job::setSpendSecretKey(uint8_t* key) +void xmrig::Job::setSpendSecretKey(const uint8_t *key) { m_hasMinerSignature = true; memcpy(m_spendSecretKey, key, sizeof(m_spendSecretKey)); - xmrig::derive_view_secret_key(m_spendSecretKey, m_viewSecretKey); - xmrig::secret_key_to_public_key(m_spendSecretKey, m_spendPublicKey); - xmrig::secret_key_to_public_key(m_viewSecretKey, m_viewPublicKey); + + derive_view_secret_key(m_spendSecretKey, m_viewSecretKey); + secret_key_to_public_key(m_spendSecretKey, m_spendPublicKey); + secret_key_to_public_key(m_viewSecretKey, m_viewPublicKey); } -void xmrig::Job::setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, const Buffer& minerTxMerkleTreeBranch) +void xmrig::Job::setMinerTx(const uint8_t *begin, const uint8_t *end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, const Buffer &minerTxMerkleTreeBranch) { m_minerTxPrefix.assign(begin, end); - m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset; - m_minerTxPubKeyOffset = minerTxPubKeyOffset; - m_minerTxMerkleTreeBranch = minerTxMerkleTreeBranch; + m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset; + m_minerTxPubKeyOffset = minerTxPubKeyOffset; + m_minerTxMerkleTreeBranch = minerTxMerkleTreeBranch; } -void xmrig::Job::generateHashingBlob(String& blob, String& signatureData) const +void xmrig::Job::generateHashingBlob(String &signatureData) { uint8_t* eph_public_key = m_minerTxPrefix.data() + m_minerTxEphPubKeyOffset; uint8_t* txkey_pub = m_minerTxPrefix.data() + m_minerTxPubKeyOffset; @@ -285,15 +308,14 @@ void xmrig::Job::generateHashingBlob(String& blob, String& signatureData) const generate_key_derivation(txkey_pub, m_viewSecretKey, derivation); derive_secret_key(derivation, 0, m_spendSecretKey, buf + 64); - signatureData = xmrig::Cvt::toHex(buf, sizeof(buf)); + signatureData = Cvt::toHex(buf, sizeof(buf)); uint8_t root_hash[32]; const uint8_t* p = m_minerTxPrefix.data(); - xmrig::BlockTemplate::CalculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, root_hash); + BlockTemplate::CalculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, root_hash); - blob = rawBlob(); const uint64_t offset = nonceOffset() + nonceSize() + BlockTemplate::SIGNATURE_SIZE + 2 /* vote */; - xmrig::Cvt::toHex(blob.data() + offset * 2, 64, root_hash, 32); + Cvt::toHex(m_rawBlob + offset * 2, 64, root_hash, 32); } diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 85b01e789..42e6947f3 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -7,8 +7,8 @@ * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2018 Lee Clagett <https://github.com/vtnerd> * Copyright 2019 Howard Chu <https://github.com/hyc> - * Copyright 2018-2020 SChernykh <https://github.com/SChernykh> - * Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com> + * Copyright 2018-2021 SChernykh <https://github.com/SChernykh> + * Copyright 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 @@ -63,6 +63,7 @@ public: bool setSeedHash(const char *hash); bool setTarget(const char *target); void setDiff(uint64_t diff); + void setSigKey(const char *sig_key); inline bool isNicehash() const { return m_nicehash; } inline bool isValid() const { return (m_size > 0 && m_diff > 0) || !m_poolWallet.isEmpty(); } @@ -102,6 +103,7 @@ public: inline const char *rawBlob() const { return m_rawBlob; } inline const char *rawTarget() const { return m_rawTarget; } inline const String &rawSeedHash() const { return m_rawSeedHash; } + inline const String &rawSigKey() const { return m_rawSigKey; } # endif static inline uint64_t toDiff(uint64_t target) { return target ? (0xFFFFFFFFFFFFFFFFULL / target) : 0; } @@ -117,13 +119,13 @@ public: # endif # ifdef XMRIG_PROXY_PROJECT - void setSpendSecretKey(uint8_t* key); - void setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, const Buffer& minerTxMerkleTreeBranch); - void generateHashingBlob(String& blob, String& signatureData) const; + void setSpendSecretKey(const uint8_t *key); + void setMinerTx(const uint8_t *begin, const uint8_t *end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, const Buffer &minerTxMerkleTreeBranch); + void generateHashingBlob(String &signatureData); # else inline const uint8_t* ephSecretKey() const { return m_hasMinerSignature ? m_ephSecretKey : nullptr; } - inline void setEphemeralKeys(uint8_t* pub_key, uint8_t* sec_key) + inline void setEphemeralKeys(const uint8_t *pub_key, const uint8_t *sec_key) { m_hasMinerSignature = true; memcpy(m_ephPublicKey, pub_key, sizeof(m_ephSecretKey)); @@ -158,12 +160,13 @@ private: char m_rawBlob[kMaxBlobSize * 2 + 8]{}; char m_rawTarget[24]{}; String m_rawSeedHash; + String m_rawSigKey; // Miner signatures - uint8_t m_spendSecretKey[32]; - uint8_t m_viewSecretKey[32]; - uint8_t m_spendPublicKey[32]; - uint8_t m_viewPublicKey[32]; + uint8_t m_spendSecretKey[32]{}; + uint8_t m_viewSecretKey[32]{}; + uint8_t m_spendPublicKey[32]{}; + uint8_t m_viewPublicKey[32]{}; mutable Buffer m_minerTxPrefix; size_t m_minerTxEphPubKeyOffset = 0; size_t m_minerTxPubKeyOffset = 0; From a30ede04f36a3b54d9fcdae654bf21d72222e37f Mon Sep 17 00:00:00 2001 From: SChernykh <sergey.v.chernykh@gmail.com> Date: Mon, 5 Jul 2021 13:56:37 +0200 Subject: [PATCH 3/8] Updates from xmrig-proxy --- src/base/net/stratum/Client.cpp | 15 ++-- src/base/net/stratum/Client.h | 4 +- src/base/net/stratum/DaemonClient.cpp | 29 +++++--- src/base/net/stratum/DaemonClient.h | 1 + src/base/net/stratum/Job.cpp | 81 ++++++++++++++++----- src/base/net/stratum/Job.h | 27 ++++--- src/base/tools/cryptonote/BlobReader.h | 2 + src/base/tools/cryptonote/BlockTemplate.cpp | 30 +++++++- src/base/tools/cryptonote/BlockTemplate.h | 2 + 9 files changed, 139 insertions(+), 52 deletions(-) diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp index 1871b6df0..95e1d8d05 100644 --- a/src/base/net/stratum/Client.cpp +++ b/src/base/net/stratum/Client.cpp @@ -6,8 +6,8 @@ * Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2019 jtgrassie <https://github.com/jtgrassie> - * Copyright 2018-2020 SChernykh <https://github.com/SChernykh> - * Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com> + * Copyright 2018-2021 SChernykh <https://github.com/SChernykh> + * Copyright 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 @@ -225,6 +225,10 @@ int64_t xmrig::Client::submit(const JobResult &result) if (result.minerSignature()) { params.AddMember("sig", StringRef(signature), allocator); } +# else + if (result.sig) { + params.AddMember("sig", StringRef(result.sig), allocator); + } # endif if (has<EXT_ALGO>() && result.algorithm.isValid()) { @@ -440,12 +444,7 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code) return false; } -# ifndef XMRIG_PROXY_PROJECT - uint8_t signatureKeyBuf[32 * 2]; - if (Cvt::fromHex(signatureKeyBuf, sizeof(signatureKeyBuf), Json::getValue(params, "sig_key"))) { - job.setEphemeralKeys(signatureKeyBuf, signatureKeyBuf + 32); - } -# endif + job.setSigKey(Json::getString(params, "sig_key")); m_job.setClientId(m_rpcId); diff --git a/src/base/net/stratum/Client.h b/src/base/net/stratum/Client.h index fdaac9f15..d9164b8a3 100644 --- a/src/base/net/stratum/Client.h +++ b/src/base/net/stratum/Client.h @@ -6,8 +6,8 @@ * Copyright 2016 Jay D Dee <jayddee246@gmail.com> * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2019 jtgrassie <https://github.com/jtgrassie> - * Copyright 2018-2020 SChernykh <https://github.com/SChernykh> - * Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com> + * Copyright 2018-2021 SChernykh <https://github.com/SChernykh> + * Copyright 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 diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 43493e752..c1d3d3a41 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -96,7 +96,7 @@ bool xmrig::DaemonClient::isTLS() const int64_t xmrig::DaemonClient::submit(const JobResult &result) { - if (result.jobId != (m_blocktemplateStr.data() + m_blocktemplateStr.size() - 32)) { + if (result.jobId != m_currentJobId) { return -1; } @@ -114,6 +114,10 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result) memcpy(data + m_blocktemplate.eph_public_key_index * 2, result.sig_data + 32 * 2, 32 * 2); } + if (result.extra_nonce >= 0) { + Cvt::toHex(data + m_blocktemplate.tx_extra_nonce_index * 2, 8, reinterpret_cast<const uint8_t*>(&result.extra_nonce), 4); + } + # else Cvt::toHex(data + m_job.nonceOffset() * 2, 8, reinterpret_cast<const uint8_t*>(&result.nonce), 4); @@ -277,6 +281,19 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) return false; } +# ifdef XMRIG_PROXY_PROJECT + const size_t k = m_blocktemplate.miner_tx_prefix_begin_index; + job.setMinerTx( + m_blocktemplate.raw_blob.data() + k, + m_blocktemplate.raw_blob.data() + m_blocktemplate.miner_tx_prefix_end_index, + m_blocktemplate.eph_public_key_index - k, + m_blocktemplate.tx_pubkey_index - k, + m_blocktemplate.tx_extra_nonce_index - k, + m_blocktemplate.tx_extra_nonce_size, + m_blocktemplate.miner_tx_merkle_tree_branch + ); +# endif + m_blockhashingblob = Json::getString(params, "blockhashing_blob"); if (m_blocktemplate.has_miner_signature) { @@ -308,13 +325,6 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) # ifdef XMRIG_PROXY_PROJECT job.setSpendSecretKey(secret_spendkey); - job.setMinerTx( - m_blocktemplate.raw_blob.data() + m_blocktemplate.miner_tx_prefix_begin_index, - m_blocktemplate.raw_blob.data() + m_blocktemplate.miner_tx_prefix_end_index, - m_blocktemplate.eph_public_key_index - m_blocktemplate.miner_tx_prefix_begin_index, - m_blocktemplate.tx_pubkey_index - m_blocktemplate.miner_tx_prefix_begin_index, - m_blocktemplate.miner_tx_merkle_tree_branch - ); # else uint8_t secret_viewkey[32]; derive_view_secret_key(secret_spendkey, secret_viewkey); @@ -377,7 +387,8 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) job.setHeight(Json::getUint64(params, kHeight)); job.setDiff(Json::getUint64(params, "difficulty")); - job.setId(blocktemplate.data() + blocktemplate.size() - 32); + m_currentJobId = Cvt::toHex(Cvt::randomBytes(4)); + job.setId(m_currentJobId); m_job = std::move(job); m_blocktemplateStr = std::move(blocktemplate); diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index 45a844646..f701240e5 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -84,6 +84,7 @@ private: } m_apiVersion = API_MONERO; std::shared_ptr<IHttpListener> m_httpListener; + String m_currentJobId; String m_blocktemplateStr; String m_blockhashingblob; String m_prevHash; diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index c92f6f015..920bf95f7 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -7,8 +7,8 @@ * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2018 Lee Clagett <https://github.com/vtnerd> * Copyright 2019 Howard Chu <https://github.com/hyc> - * Copyright 2018-2020 SChernykh <https://github.com/SChernykh> - * Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com> + * Copyright 2018-2021 SChernykh <https://github.com/SChernykh> + * Copyright 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 @@ -144,6 +144,25 @@ void xmrig::Job::setDiff(uint64_t diff) } +void xmrig::Job::setSigKey(const char *sig_key) +{ + constexpr const size_t size = 64; + + if (!sig_key || strlen(sig_key) != size * 2) { + return; + } + +# ifndef XMRIG_PROXY_PROJECT + const auto buf = Cvt::fromHex(sig_key, size * 2); + if (buf.size() == size) { + setEphemeralKeys(buf.data(), buf.data() + 32); + } +# else + m_rawSigKey = sig_key; +# endif +} + + void xmrig::Job::copy(const Job &other) { m_algorithm = other.m_algorithm; @@ -164,6 +183,7 @@ void xmrig::Job::copy(const Job &other) # ifdef XMRIG_PROXY_PROJECT m_rawSeedHash = other.m_rawSeedHash; + m_rawSigKey = other.m_rawSigKey; memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob)); memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget)); @@ -181,6 +201,8 @@ void xmrig::Job::copy(const Job &other) m_minerTxPrefix = other.m_minerTxPrefix; m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset; m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset; + m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset; + m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize; m_minerTxMerkleTreeBranch = other.m_minerTxMerkleTreeBranch; # else memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey)); @@ -215,6 +237,7 @@ void xmrig::Job::move(Job &&other) # ifdef XMRIG_PROXY_PROJECT m_rawSeedHash = std::move(other.m_rawSeedHash); + m_rawSigKey = std::move(other.m_rawSigKey); memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob)); memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget)); @@ -229,10 +252,13 @@ void xmrig::Job::move(Job &&other) memcpy(m_viewSecretKey, other.m_viewSecretKey, sizeof(m_viewSecretKey)); memcpy(m_spendPublicKey, other.m_spendPublicKey, sizeof(m_spendPublicKey)); memcpy(m_viewPublicKey, other.m_viewPublicKey, sizeof(m_viewPublicKey)); - m_minerTxPrefix = std::move(other.m_minerTxPrefix); - m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset; - m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset; - m_minerTxMerkleTreeBranch = std::move(other.m_minerTxMerkleTreeBranch); + + m_minerTxPrefix = std::move(other.m_minerTxPrefix); + m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset; + m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset; + m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset; + m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize; + m_minerTxMerkleTreeBranch = std::move(other.m_minerTxMerkleTreeBranch); # else memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey)); memcpy(m_ephSecretKey, other.m_ephSecretKey, sizeof(m_ephSecretKey)); @@ -245,26 +271,35 @@ void xmrig::Job::move(Job &&other) #ifdef XMRIG_PROXY_PROJECT -void xmrig::Job::setSpendSecretKey(uint8_t* key) +void xmrig::Job::setSpendSecretKey(const uint8_t *key) { m_hasMinerSignature = true; memcpy(m_spendSecretKey, key, sizeof(m_spendSecretKey)); - xmrig::derive_view_secret_key(m_spendSecretKey, m_viewSecretKey); - xmrig::secret_key_to_public_key(m_spendSecretKey, m_spendPublicKey); - xmrig::secret_key_to_public_key(m_viewSecretKey, m_viewPublicKey); + + derive_view_secret_key(m_spendSecretKey, m_viewSecretKey); + secret_key_to_public_key(m_spendSecretKey, m_spendPublicKey); + secret_key_to_public_key(m_viewSecretKey, m_viewPublicKey); } -void xmrig::Job::setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, const Buffer& minerTxMerkleTreeBranch) +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) { m_minerTxPrefix.assign(begin, end); - m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset; - m_minerTxPubKeyOffset = minerTxPubKeyOffset; - m_minerTxMerkleTreeBranch = minerTxMerkleTreeBranch; + m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset; + m_minerTxPubKeyOffset = minerTxPubKeyOffset; + m_minerTxExtraNonceOffset = minerTxExtraNonceOffset; + m_minerTxExtraNonceSize = minerTxExtraNonceSize; + m_minerTxMerkleTreeBranch = minerTxMerkleTreeBranch; } -void xmrig::Job::generateHashingBlob(String& blob, String& signatureData) const +void xmrig::Job::setExtraNonceInMinerTx(uint32_t extra_nonce) +{ + memcpy(m_minerTxPrefix.data() + m_minerTxExtraNonceOffset, &extra_nonce, std::min(m_minerTxExtraNonceSize, sizeof(uint32_t))); +} + + +void xmrig::Job::generateSignatureData(String &signatureData) const { uint8_t* eph_public_key = m_minerTxPrefix.data() + m_minerTxEphPubKeyOffset; uint8_t* txkey_pub = m_minerTxPrefix.data() + m_minerTxPubKeyOffset; @@ -285,15 +320,23 @@ void xmrig::Job::generateHashingBlob(String& blob, String& signatureData) const generate_key_derivation(txkey_pub, m_viewSecretKey, derivation); derive_secret_key(derivation, 0, m_spendSecretKey, buf + 64); - signatureData = xmrig::Cvt::toHex(buf, sizeof(buf)); + signatureData = Cvt::toHex(buf, sizeof(buf)); +} +void xmrig::Job::generateHashingBlob(String &blob) const +{ uint8_t root_hash[32]; const uint8_t* p = m_minerTxPrefix.data(); - xmrig::BlockTemplate::CalculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, root_hash); + BlockTemplate::CalculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, root_hash); + + uint64_t root_hash_offset = nonceOffset() + nonceSize(); + + if (m_hasMinerSignature) { + root_hash_offset += BlockTemplate::SIGNATURE_SIZE + 2 /* vote */; + } blob = rawBlob(); - const uint64_t offset = nonceOffset() + nonceSize() + BlockTemplate::SIGNATURE_SIZE + 2 /* vote */; - xmrig::Cvt::toHex(blob.data() + offset * 2, 64, root_hash, 32); + Cvt::toHex(blob.data() + root_hash_offset * 2, 64, root_hash, BlockTemplate::HASH_SIZE); } diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 85b01e789..c72902756 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -7,8 +7,8 @@ * Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt> * Copyright 2018 Lee Clagett <https://github.com/vtnerd> * Copyright 2019 Howard Chu <https://github.com/hyc> - * Copyright 2018-2020 SChernykh <https://github.com/SChernykh> - * Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com> + * Copyright 2018-2021 SChernykh <https://github.com/SChernykh> + * Copyright 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 @@ -63,6 +63,7 @@ public: bool setSeedHash(const char *hash); bool setTarget(const char *target); void setDiff(uint64_t diff); + void setSigKey(const char *sig_key); inline bool isNicehash() const { return m_nicehash; } inline bool isValid() const { return (m_size > 0 && m_diff > 0) || !m_poolWallet.isEmpty(); } @@ -102,6 +103,7 @@ public: inline const char *rawBlob() const { return m_rawBlob; } inline const char *rawTarget() const { return m_rawTarget; } inline const String &rawSeedHash() const { return m_rawSeedHash; } + inline const String &rawSigKey() const { return m_rawSigKey; } # endif static inline uint64_t toDiff(uint64_t target) { return target ? (0xFFFFFFFFFFFFFFFFULL / target) : 0; } @@ -117,13 +119,15 @@ public: # endif # ifdef XMRIG_PROXY_PROJECT - void setSpendSecretKey(uint8_t* key); - void setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, const Buffer& minerTxMerkleTreeBranch); - void generateHashingBlob(String& blob, String& signatureData) const; + 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); + void setExtraNonceInMinerTx(uint32_t extra_nonce); + void generateSignatureData(String& signatureData) const; + void generateHashingBlob(String& blob) const; # else inline const uint8_t* ephSecretKey() const { return m_hasMinerSignature ? m_ephSecretKey : nullptr; } - inline void setEphemeralKeys(uint8_t* pub_key, uint8_t* sec_key) + inline void setEphemeralKeys(const uint8_t *pub_key, const uint8_t *sec_key) { m_hasMinerSignature = true; memcpy(m_ephPublicKey, pub_key, sizeof(m_ephSecretKey)); @@ -158,15 +162,18 @@ private: char m_rawBlob[kMaxBlobSize * 2 + 8]{}; char m_rawTarget[24]{}; String m_rawSeedHash; + String m_rawSigKey; // Miner signatures - uint8_t m_spendSecretKey[32]; - uint8_t m_viewSecretKey[32]; - uint8_t m_spendPublicKey[32]; - uint8_t m_viewPublicKey[32]; + uint8_t m_spendSecretKey[32]{}; + uint8_t m_viewSecretKey[32]{}; + uint8_t m_spendPublicKey[32]{}; + uint8_t m_viewPublicKey[32]{}; mutable Buffer m_minerTxPrefix; size_t m_minerTxEphPubKeyOffset = 0; size_t m_minerTxPubKeyOffset = 0; + size_t m_minerTxExtraNonceOffset = 0; + size_t m_minerTxExtraNonceSize = 0; Buffer m_minerTxMerkleTreeBranch; # else // Miner signatures diff --git a/src/base/tools/cryptonote/BlobReader.h b/src/base/tools/cryptonote/BlobReader.h index 58f81e2dd..f10bcd88b 100644 --- a/src/base/tools/cryptonote/BlobReader.h +++ b/src/base/tools/cryptonote/BlobReader.h @@ -61,6 +61,8 @@ public: inline size_t index() const { return m_index; } + inline void skip(size_t N) { m_index += N; } + private: inline bool getByte(uint8_t& data) { diff --git a/src/base/tools/cryptonote/BlockTemplate.cpp b/src/base/tools/cryptonote/BlockTemplate.cpp index 0b54c3998..5449ec23c 100644 --- a/src/base/tools/cryptonote/BlockTemplate.cpp +++ b/src/base/tools/cryptonote/BlockTemplate.cpp @@ -86,13 +86,35 @@ bool BlockTemplate::Init(const String& blockTemplate, Coin coin) ar(eph_public_key); ar(extra_size); - tx_pubkey_index = ar.index() + 1; + const uint64_t tx_extra_index = ar.index(); ar.readItems(extra, extra_size); - // First thing in tx_extra must be TX_EXTRA_TAG_PUBKEY - if (extra[0] != 0x01) - return false; + CBlobReader ar_extra(extra.data(), extra_size); + + tx_extra_nonce_size = 0; + tx_extra_nonce_index = 0; + + while (ar_extra.index() < extra_size) { + uint64_t extra_tag; + ar_extra(extra_tag); + + switch (extra_tag) { + case 0x01: // TX_EXTRA_TAG_PUBKEY + tx_pubkey_index = tx_extra_index + ar_extra.index(); + ar_extra.skip(KEY_SIZE); + break; + + case 0x02: // TX_EXTRA_NONCE + ar_extra(tx_extra_nonce_size); + tx_extra_nonce_index = tx_extra_index + ar_extra.index(); + ar_extra.skip(tx_extra_nonce_size); + break; + + default: + return false; // TODO: handle other tags + } + } miner_tx_prefix_end_index = ar.index(); // Prefix end diff --git a/src/base/tools/cryptonote/BlockTemplate.h b/src/base/tools/cryptonote/BlockTemplate.h index e80ece141..4a6ef8051 100644 --- a/src/base/tools/cryptonote/BlockTemplate.h +++ b/src/base/tools/cryptonote/BlockTemplate.h @@ -42,6 +42,8 @@ struct BlockTemplate Buffer raw_blob; size_t eph_public_key_index; size_t tx_pubkey_index; + uint64_t tx_extra_nonce_size; + size_t tx_extra_nonce_index; size_t miner_tx_prefix_begin_index; size_t miner_tx_prefix_end_index; From 93805cd167345e3bdd956263a495853b36184480 Mon Sep 17 00:00:00 2001 From: XMRig <support@xmrig.com> Date: Tue, 6 Jul 2021 23:07:31 +0700 Subject: [PATCH 4/8] #2476 Fixed crash in DMI memory reader. --- src/hw/dmi/DmiMemory.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hw/dmi/DmiMemory.cpp b/src/hw/dmi/DmiMemory.cpp index 883c89b5e..a07f5b550 100644 --- a/src/hw/dmi/DmiMemory.cpp +++ b/src/hw/dmi/DmiMemory.cpp @@ -230,6 +230,10 @@ void xmrig::DmiMemory::setId(const char *slot, const char *bank) m_slot = slot; m_bank = bank; + if (!slot || !bank) { + return; + } + try { std::cmatch cm; if (std::regex_match(slot, cm, std::regex("^Channel([A-Z])[-_]DIMM(\\d+)$", std::regex_constants::icase))) { From 0842e6b9d26422b8abd35e3a918128ff946aed4d Mon Sep 17 00:00:00 2001 From: SChernykh <sergey.v.chernykh@gmail.com> Date: Thu, 15 Jul 2021 11:13:14 +0200 Subject: [PATCH 5/8] ZeroMQ support for solo mining Gets new blocks from daemon immediately without polling, saving ~0.5 seconds on average when daemon gets new block from the network. Also saves some CPU cycles because it doesn't need to poll daemon every second. Testing: add "daemon-zmq-port": 28083 to xmrig's pool config in config.json and run ./monerod --testnet --zmq-pub tcp://127.0.0.1:28083 --- src/base/base.cmake | 1 + src/base/kernel/config/BaseTransform.cpp | 18 +- src/base/kernel/interfaces/IConfig.h | 1 + src/base/net/stratum/DaemonClient.cpp | 369 +++++++++++++++++++- src/base/net/stratum/DaemonClient.h | 45 ++- src/base/net/stratum/Pool.cpp | 6 + src/base/net/stratum/Pool.h | 3 + src/base/tools/bswap_64.h | 37 ++ src/base/tools/cryptonote/BlockTemplate.cpp | 2 +- src/core/config/Config_platform.h | 1 + src/crypto/astrobwt/AstroBWT.cpp | 16 +- src/net/Network.cpp | 18 +- 12 files changed, 482 insertions(+), 35 deletions(-) create mode 100644 src/base/tools/bswap_64.h diff --git a/src/base/base.cmake b/src/base/base.cmake index 92c16c0d7..1359dd8a0 100644 --- a/src/base/base.cmake +++ b/src/base/base.cmake @@ -70,6 +70,7 @@ set(HEADERS_BASE src/base/net/tools/Storage.h src/base/tools/Arguments.h src/base/tools/Baton.h + src/base/tools/bswap_64.h src/base/tools/Buffer.h src/base/tools/Chrono.h src/base/tools/Cvt.h diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index 1036ae295..6d4f38d01 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -242,13 +242,14 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch return set(doc, BaseConfig::kTls, TlsConfig::kGen, arg); # endif - case IConfig::RetriesKey: /* --retries */ - case IConfig::RetryPauseKey: /* --retry-pause */ - case IConfig::PrintTimeKey: /* --print-time */ - case IConfig::HttpPort: /* --http-port */ - case IConfig::DonateLevelKey: /* --donate-level */ - case IConfig::DaemonPollKey: /* --daemon-poll-interval */ - case IConfig::DnsTtlKey: /* --dns-ttl */ + case IConfig::RetriesKey: /* --retries */ + case IConfig::RetryPauseKey: /* --retry-pause */ + case IConfig::PrintTimeKey: /* --print-time */ + case IConfig::HttpPort: /* --http-port */ + case IConfig::DonateLevelKey: /* --donate-level */ + case IConfig::DaemonPollKey: /* --daemon-poll-interval */ + case IConfig::DnsTtlKey: /* --dns-ttl */ + case IConfig::DaemonZMQPortKey: /* --daemon-zmq-port */ return transformUint64(doc, key, static_cast<uint64_t>(strtol(arg, nullptr, 10))); case IConfig::BackgroundKey: /* --background */ @@ -359,6 +360,9 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui # ifdef XMRIG_FEATURE_HTTP case IConfig::DaemonPollKey: /* --daemon-poll-interval */ return add(doc, Pools::kPools, Pool::kDaemonPollInterval, arg); + + case IConfig::DaemonZMQPortKey: /* --daemon-zmq-port */ + return add(doc, Pools::kPools, Pool::kDaemonZMQPort, arg); # endif default: diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index d1260afa8..e531353aa 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -85,6 +85,7 @@ public: DnsIPv6Key = 1053, DnsTtlKey = 1054, SpendSecretKey = 1055, + DaemonZMQPortKey = 1056, // xmrig common CPUPriorityKey = 1021, diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index c1d3d3a41..77818f34c 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -31,10 +31,14 @@ #include "base/io/json/JsonRequest.h" #include "base/io/log/Log.h" #include "base/kernel/interfaces/IClientListener.h" +#include "base/net/dns/Dns.h" +#include "base/net/dns/DnsRecords.h" #include "base/net/http/Fetch.h" #include "base/net/http/HttpData.h" #include "base/net/http/HttpListener.h" #include "base/net/stratum/SubmitResult.h" +#include "base/net/tools/NetBuffer.h" +#include "base/tools/bswap_64.h" #include "base/tools/Cvt.h" #include "base/tools/Timer.h" #include "base/tools/cryptonote/Signatures.h" @@ -48,7 +52,11 @@ namespace xmrig { -static const char *kBlocktemplateBlob = "blocktemplate_blob"; + +Storage<DaemonClient> DaemonClient::m_storage; + + +static const char* kBlocktemplateBlob = "blocktemplate_blob"; static const char *kGetHeight = "/getheight"; static const char *kGetInfo = "/getinfo"; static const char *kHash = "hash"; @@ -57,6 +65,12 @@ static const char *kJsonRPC = "/json_rpc"; static constexpr size_t kBlobReserveSize = 8; +static const char kZMQGreeting[64] = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 127, 3, 0, 'N', 'U', 'L', 'L' }; +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"; + } @@ -65,12 +79,25 @@ xmrig::DaemonClient::DaemonClient(int id, IClientListener *listener) : { m_httpListener = std::make_shared<HttpListener>(this); m_timer = new Timer(this); + m_key = m_storage.add(this); } xmrig::DaemonClient::~DaemonClient() { delete m_timer; + delete m_ZMQSocket; +} + + +void xmrig::DaemonClient::deleteLater() +{ + if (m_pool.zmq_port() >= 0) { + ZMQClose(true); + } + else { + delete this; + } } @@ -159,7 +186,13 @@ void xmrig::DaemonClient::connect() } setState(ConnectingState); - getBlockTemplate(); + + if (m_pool.zmq_port() >= 0) { + m_dns = Dns::resolve(m_pool.host(), this); + } + else { + getBlockTemplate(); + } } @@ -238,7 +271,7 @@ void xmrig::DaemonClient::onHttpData(const HttpData &data) void xmrig::DaemonClient::onTimer(const Timer *) { if (m_state == ConnectingState) { - getBlockTemplate(); + connect(); } else if (m_state == ConnectedState) { if (m_apiVersion == API_DERO) { @@ -251,6 +284,43 @@ void xmrig::DaemonClient::onTimer(const Timer *) } +void xmrig::DaemonClient::onResolved(const DnsRecords& records, int status, const char* error) +{ + m_dns.reset(); + + if (status < 0 && records.isEmpty()) { + if (!isQuiet()) { + LOG_ERR("%s " RED("DNS error: ") RED_BOLD("\"%s\""), tag(), error); + } + + retry(); + return; + } + + if (m_ZMQSocket) { + delete m_ZMQSocket; + } + + const auto& record = records.get(); + m_ip = record.ip(); + + uv_connect_t* 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_init(uv_default_loop(), m_ZMQSocket); + uv_tcp_nodelay(m_ZMQSocket, 1); + +# ifndef WIN32 + uv_tcp_keepalive(m_ZMQSocket, 1, 60); +# endif + + uv_tcp_connect(req, m_ZMQSocket, record.addr(m_pool.zmq_port()), onZMQConnect); +} + + bool xmrig::DaemonClient::isOutdated(uint64_t height, const char *hash) const { return m_job.height() != height || m_prevHash != hash; @@ -452,7 +522,9 @@ bool xmrig::DaemonClient::parseResponse(int64_t id, const rapidjson::Value &resu } if (handleSubmitResponse(id, error_msg)) { - getBlockTemplate(); + if (error_msg || (m_pool.zmq_port() < 0)) { + getBlockTemplate(); + } return true; } @@ -504,6 +576,10 @@ void xmrig::DaemonClient::retry() setState(ConnectingState); } + if ((m_ZMQConnectionState != ZMQ_NOT_CONNECTED) && (m_ZMQConnectionState != ZMQ_DISCONNECTING)) { + uv_close(reinterpret_cast<uv_handle_t*>(m_ZMQSocket), onZMQClose); + } + m_timer->stop(); m_timer->start(m_retryPause, 0); } @@ -531,8 +607,10 @@ void xmrig::DaemonClient::setState(SocketState state) m_failures = 0; m_listener->onLoginSuccess(this); - const uint64_t interval = std::max<uint64_t>(20, m_pool.pollInterval()); - m_timer->start(interval, interval); + if (m_pool.zmq_port() < 0) { + const uint64_t interval = std::max<uint64_t>(20, m_pool.pollInterval()); + m_timer->start(interval, interval); + } } break; @@ -545,3 +623,282 @@ void xmrig::DaemonClient::setState(SocketState state) break; } } + + +void xmrig::DaemonClient::onZMQConnect(uv_connect_t* req, int status) +{ + DaemonClient* client = getClient(req->data); + delete req; + + if (!client) { + return; + } + + if (status < 0) { + LOG_ERR("%s " RED("ZMQ connect error: ") RED_BOLD("\"%s\""), client->tag(), uv_strerror(status)); + client->retry(); + return; + } + + client->ZMQConnected(); +} + + +void xmrig::DaemonClient::onZMQRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) +{ + DaemonClient* client = getClient(stream->data); + if (client) { + client->ZMQRead(nread, buf); + } + + NetBuffer::release(buf); +} + + +void xmrig::DaemonClient::onZMQClose(uv_handle_t* handle) +{ + DaemonClient* client = getClient(handle->data); + if (client) { +# ifdef APP_DEBUG + LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" disconnected"), client->m_pool.host().data(), client->m_pool.zmq_port()); +# endif + client->m_ZMQConnectionState = ZMQ_NOT_CONNECTED; + } +} + + +void xmrig::DaemonClient::onZMQShutdown(uv_handle_t* handle) +{ + DaemonClient* client = getClient(handle->data); + if (client) { +# ifdef APP_DEBUG + LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" shutdown"), client->m_pool.host().data(), client->m_pool.zmq_port()); +# endif + client->m_ZMQConnectionState = ZMQ_NOT_CONNECTED; + m_storage.remove(client->m_key); + } +} + + +void xmrig::DaemonClient::ZMQConnected() +{ +# ifdef APP_DEBUG + LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" connected"), m_pool.host().data(), m_pool.zmq_port()); +# endif + + m_ZMQConnectionState = ZMQ_GREETING_1; + m_ZMQSendBuf.reserve(256); + m_ZMQRecvBuf.reserve(256); + + if (ZMQWrite(kZMQGreeting, kZMQGreetingSize1)) { + uv_read_start(reinterpret_cast<uv_stream_t*>(m_ZMQSocket), NetBuffer::onAlloc, onZMQRead); + } +} + + +bool xmrig::DaemonClient::ZMQWrite(const char* data, size_t size) +{ + m_ZMQSendBuf.assign(data, data + size); + + uv_buf_t buf; + buf.base = m_ZMQSendBuf.data(); + buf.len = static_cast<uint32_t>(m_ZMQSendBuf.size()); + + const int rc = uv_try_write(reinterpret_cast<uv_stream_t*>(m_ZMQSocket), &buf, 1); + + if (static_cast<size_t>(rc) == buf.len) { + return true; + } + + LOG_ERR("%s " RED("ZMQ write failed, rc = %d"), tag(), rc); + ZMQClose(); + return false; +} + + +void xmrig::DaemonClient::ZMQRead(ssize_t nread, const uv_buf_t* buf) +{ + if (nread <= 0) { + LOG_ERR("%s " RED("ZMQ read failed, nread = %" PRId64), tag(), nread); + ZMQClose(); + return; + } + + m_ZMQRecvBuf.insert(m_ZMQRecvBuf.end(), buf->base, buf->base + nread); + + do { + switch (m_ZMQConnectionState) { + case ZMQ_GREETING_1: + if (m_ZMQRecvBuf.size() >= kZMQGreetingSize1) { + if ((m_ZMQRecvBuf[0] == -1) && (m_ZMQRecvBuf[9] == 127) && (m_ZMQRecvBuf[10] == 3)) { + ZMQWrite(kZMQGreeting + kZMQGreetingSize1, sizeof(kZMQGreeting) - kZMQGreetingSize1); + m_ZMQConnectionState = ZMQ_GREETING_2; + break; + } + else { + LOG_ERR("%s " RED("ZMQ handshake failed: invalid greeting format"), tag()); + ZMQClose(); + } + } + return; + + case ZMQ_GREETING_2: + if (m_ZMQRecvBuf.size() >= sizeof(kZMQGreeting)) { + if (memcmp(m_ZMQRecvBuf.data() + 12, kZMQGreeting + 12, 20) == 0) { + m_ZMQConnectionState = ZMQ_HANDSHAKE; + m_ZMQRecvBuf.erase(m_ZMQRecvBuf.begin(), m_ZMQRecvBuf.begin() + sizeof(kZMQGreeting)); + + ZMQWrite(kZMQHandshake, sizeof(kZMQHandshake) - 1); + break; + } + else { + LOG_ERR("%s " RED("ZMQ handshake failed: invalid greeting format 2"), tag()); + ZMQClose(); + } + } + return; + + case ZMQ_HANDSHAKE: + if (m_ZMQRecvBuf.size() >= 2) { + if (m_ZMQRecvBuf[0] != 4) { + LOG_ERR("%s " RED("ZMQ handshake failed: invalid handshake format"), tag()); + ZMQClose(); + return; + } + + const size_t size = static_cast<unsigned char>(m_ZMQRecvBuf[1]); + if (size < 18) { + LOG_ERR("%s " RED("ZMQ handshake failed: invalid handshake size"), tag()); + ZMQClose(); + return; + } + + if (m_ZMQRecvBuf.size() < size + 2) { + return; + } + + if (memcmp(m_ZMQRecvBuf.data() + 2, kZMQHandshake + 2, 18) != 0) { + LOG_ERR("%s " RED("ZMQ handshake failed: invalid handshake data"), tag()); + ZMQClose(); + return; + } + + ZMQWrite(kZMQSubscribe, sizeof(kZMQSubscribe) - 1); + + m_ZMQConnectionState = ZMQ_CONNECTED; + m_ZMQRecvBuf.erase(m_ZMQRecvBuf.begin(), m_ZMQRecvBuf.begin() + size + 2); + + getBlockTemplate(); + break; + } + return; + + case ZMQ_CONNECTED: + ZMQParse(); + return; + + default: + return; + } + } while (true); +} + + +void xmrig::DaemonClient::ZMQParse() +{ +# ifdef APP_DEBUG + std::vector<char> msg; +# endif + + size_t msg_size = 0; + + char* data = m_ZMQRecvBuf.data(); + size_t avail = m_ZMQRecvBuf.size(); + bool more; + + do { + if (avail < 1) { + return; + } + + more = (data[0] & 1) != 0; + const bool long_size = (data[0] & 2) != 0; + const bool command = (data[0] & 4) != 0; + + ++data; + --avail; + + uint64_t size = 0; + if (long_size) + { + if (avail < sizeof(uint64_t)) { + return; + } + size = bswap_64(*((uint64_t*)data)); + data += sizeof(uint64_t); + avail -= sizeof(uint64_t); + } + else + { + if (avail < sizeof(uint8_t)) { + return; + } + size = static_cast<uint8_t>(*data); + ++data; + --avail; + } + + if (size > 1024U - msg_size) + { + LOG_ERR("%s " RED("ZMQ message is too large, size = %" PRIu64 " bytes"), tag(), size); + ZMQClose(); + return; + } + + if (avail < size) { + return; + } + + if (!command) { +# ifdef APP_DEBUG + msg.insert(msg.end(), data, data + size); +# endif + + msg_size += size; + } + + data += size; + avail -= size; + } while (more); + + m_ZMQRecvBuf.erase(m_ZMQRecvBuf.begin(), m_ZMQRecvBuf.begin() + (data - m_ZMQRecvBuf.data())); + +# ifdef APP_DEBUG + LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" read ") CYAN_BOLD("%zu") BLACK_BOLD(" bytes") " %s", m_pool.host().data(), m_pool.zmq_port(), msg.size(), msg.data()); +# endif + + getBlockTemplate(); +} + + +bool xmrig::DaemonClient::ZMQClose(bool shutdown) +{ + if ((m_ZMQConnectionState == ZMQ_NOT_CONNECTED) || (m_ZMQConnectionState == ZMQ_DISCONNECTING)) { + if (shutdown) { + m_storage.remove(m_key); + } + return false; + } + + m_ZMQConnectionState = ZMQ_DISCONNECTING; + + if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_ZMQSocket)) == 0) { + uv_close(reinterpret_cast<uv_handle_t*>(m_ZMQSocket), shutdown ? onZMQShutdown : onZMQClose); + if (!shutdown) { + retry(); + } + return true; + } + + return false; +} diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index f701240e5..2844d15fe 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -27,11 +27,16 @@ #define XMRIG_DAEMONCLIENT_H +#include <uv.h> + + +#include "base/kernel/interfaces/IDnsListener.h" #include "base/kernel/interfaces/IHttpListener.h" #include "base/kernel/interfaces/ITimerListener.h" #include "base/net/stratum/BaseClient.h" #include "base/tools/Object.h" #include "base/tools/cryptonote/BlockTemplate.h" +#include "base/net/tools/Storage.h" #include <memory> @@ -40,7 +45,10 @@ namespace xmrig { -class DaemonClient : public BaseClient, public ITimerListener, public IHttpListener +class DnsRequest; + + +class DaemonClient : public BaseClient, public IDnsListener, public ITimerListener, public IHttpListener { public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(DaemonClient) @@ -57,6 +65,7 @@ protected: void onHttpData(const HttpData &data) override; void onTimer(const Timer *timer) override; + void onResolved(const DnsRecords& records, int status, const char* error) override; inline bool hasExtension(Extension) const noexcept override { return false; } inline const char *mode() const override { return "daemon"; } @@ -64,7 +73,7 @@ protected: inline const char *tlsVersion() const override { return m_tlsVersion; } inline int64_t send(const rapidjson::Value &, Callback) override { return -1; } inline int64_t send(const rapidjson::Value &) override { return -1; } - inline void deleteLater() override { delete this; } + void deleteLater() override; inline void tick(uint64_t) override {} private: @@ -95,6 +104,38 @@ private: String m_blocktemplateRequestHash; BlockTemplate m_blocktemplate; + +private: + static inline DaemonClient* getClient(void* data) { return m_storage.get(data); } + + uintptr_t m_key = 0; + static Storage<DaemonClient> m_storage; + + static void onZMQConnect(uv_connect_t* req, int status); + static void onZMQRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf); + static void onZMQClose(uv_handle_t* handle); + static void onZMQShutdown(uv_handle_t* handle); + + void ZMQConnected(); + bool ZMQWrite(const char* data, size_t size); + void ZMQRead(ssize_t nread, const uv_buf_t* buf); + void ZMQParse(); + bool ZMQClose(bool shutdown = false); + + std::shared_ptr<DnsRequest> m_dns; + uv_tcp_t* m_ZMQSocket = nullptr; + + enum { + ZMQ_NOT_CONNECTED, + ZMQ_GREETING_1, + ZMQ_GREETING_2, + ZMQ_HANDSHAKE, + ZMQ_CONNECTED, + ZMQ_DISCONNECTING, + } m_ZMQConnectionState = ZMQ_NOT_CONNECTED; + + std::vector<char> m_ZMQSendBuf; + std::vector<char> m_ZMQRecvBuf; }; diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index 86e3205e2..427a7e8fc 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -66,6 +66,7 @@ const char *Pool::kAlgo = "algo"; const char *Pool::kCoin = "coin"; const char *Pool::kDaemon = "daemon"; const char *Pool::kDaemonPollInterval = "daemon-poll-interval"; +const char *Pool::kDaemonZMQPort = "daemon-zmq-port"; const char *Pool::kEnabled = "enabled"; const char *Pool::kFingerprint = "tls-fingerprint"; const char *Pool::kKeepalive = "keepalive"; @@ -127,6 +128,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) : m_coin = Json::getString(object, kCoin); m_daemon = Json::getString(object, kSelfSelect); m_proxy = Json::getValue(object, kSOCKS5); + m_zmqPort = Json::getInt(object, kDaemonZMQPort, m_zmqPort); m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true)); m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash) || m_url.host().contains(kNicehashHost)); @@ -301,6 +303,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const if (m_mode == MODE_DAEMON) { obj.AddMember(StringRef(kDaemonPollInterval), m_pollInterval, allocator); + obj.AddMember(StringRef(kDaemonZMQPort), m_zmqPort, allocator); } else { obj.AddMember(StringRef(kSelfSelect), m_daemon.url().toJSON(), allocator); @@ -336,6 +339,9 @@ void xmrig::Pool::print() const LOG_NOTICE("url: %s", url().data()); LOG_DEBUG ("host: %s", host().data()); LOG_DEBUG ("port: %d", static_cast<int>(port())); + if (m_zmqPort >= 0) { + LOG_DEBUG("zmq-port: %d", m_zmqPort); + } LOG_DEBUG ("user: %s", m_user.data()); LOG_DEBUG ("pass: %s", m_password.data()); LOG_DEBUG ("rig-id %s", m_rigId.data()); diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index c7abbbf38..4eb00ec01 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -72,6 +72,7 @@ public: static const char *kUrl; static const char *kUser; static const char* kSpendSecretKey; + static const char* kDaemonZMQPort; static const char *kNicehashHost; constexpr static int kKeepAliveTimeout = 60; @@ -107,6 +108,7 @@ public: inline int keepAlive() const { return m_keepAlive; } inline Mode mode() const { return m_mode; } inline uint16_t port() const { return m_url.port(); } + inline int zmq_port() const { return m_zmqPort; } inline uint64_t pollInterval() const { return m_pollInterval; } inline void setAlgo(const Algorithm &algorithm) { m_algorithm = algorithm; } inline void setPassword(const String &password) { m_password = password; } @@ -155,6 +157,7 @@ private: uint64_t m_pollInterval = kDefaultPollInterval; Url m_daemon; Url m_url; + int m_zmqPort = -1; # ifdef XMRIG_FEATURE_BENCHMARK std::shared_ptr<BenchConfig> m_benchmark; diff --git a/src/base/tools/bswap_64.h b/src/base/tools/bswap_64.h new file mode 100644 index 000000000..96335c64e --- /dev/null +++ b/src/base/tools/bswap_64.h @@ -0,0 +1,37 @@ +/* XMRig + * 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/>. + */ + +#ifndef XMRIG_BSWAP_64_H +#define XMRIG_BSWAP_64_H + +#ifdef _MSC_VER + +#include <stdlib.h> +#define bswap_64(x) _byteswap_uint64(x) + +#elif defined __GNUC__ + +#define bswap_64(x) __builtin_bswap64(x) + +#else + +#include <byteswap.h> + +#endif + +#endif /* XMRIG_BSWAP_64_H */ diff --git a/src/base/tools/cryptonote/BlockTemplate.cpp b/src/base/tools/cryptonote/BlockTemplate.cpp index 5449ec23c..29653441d 100644 --- a/src/base/tools/cryptonote/BlockTemplate.cpp +++ b/src/base/tools/cryptonote/BlockTemplate.cpp @@ -96,7 +96,7 @@ bool BlockTemplate::Init(const String& blockTemplate, Coin coin) tx_extra_nonce_index = 0; while (ar_extra.index() < extra_size) { - uint64_t extra_tag; + uint64_t extra_tag = 0; ar_extra(extra_tag); switch (extra_tag) { diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index 2867a8b7a..7194f5cc5 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -52,6 +52,7 @@ static const option options[] = { { "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey }, { "self-select", 1, nullptr, IConfig::SelfSelectKey }, { "submit-to-origin", 0, nullptr, IConfig::SubmitToOriginKey }, + { "daemon-zmq-port", 1, nullptr, IConfig::DaemonZMQPortKey }, # endif { "av", 1, nullptr, IConfig::AVKey }, { "background", 0, nullptr, IConfig::BackgroundKey }, diff --git a/src/crypto/astrobwt/AstroBWT.cpp b/src/crypto/astrobwt/AstroBWT.cpp index 2286a5fe2..3e3622530 100644 --- a/src/crypto/astrobwt/AstroBWT.cpp +++ b/src/crypto/astrobwt/AstroBWT.cpp @@ -30,6 +30,7 @@ #include "crypto/astrobwt/AstroBWT.h" #include "backend/cpu/Cpu.h" #include "base/crypto/sha3.h" +#include "base/tools/bswap_64.h" #include "crypto/cn/CryptoNight.h" @@ -54,21 +55,6 @@ __attribute__((ms_abi)) void SHA3_256_AVX2_ASM(const void* in, size_t inBytes, void* out); #endif -#ifdef _MSC_VER - -#include <stdlib.h> -#define bswap_64(x) _byteswap_uint64(x) - -#elif defined __GNUC__ - -#define bswap_64(x) __builtin_bswap64(x) - -#else - -#include <byteswap.h> - -#endif - #ifdef XMRIG_ARM extern "C" { #include "salsa20_ref/ecrypt-sync.h" diff --git a/src/net/Network.cpp b/src/net/Network.cpp index fb8b21b3d..64a1b689e 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -137,9 +137,14 @@ void xmrig::Network::onActive(IStrategy *strategy, IClient *client) } # endif + char zmq_buf[32] = {}; + if (client->pool().zmq_port() >= 0) { + snprintf(zmq_buf, sizeof(zmq_buf), " (ZMQ:%d)", client->pool().zmq_port()); + } + const char *tlsVersion = client->tlsVersion(); - LOG_INFO("%s " WHITE_BOLD("use %s ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"), - Tags::network(), client->mode(), pool.host().data(), pool.port(), tlsVersion ? tlsVersion : "", client->ip().data()); + LOG_INFO("%s " WHITE_BOLD("use %s ") CYAN_BOLD("%s:%d%s ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"), + Tags::network(), client->mode(), pool.host().data(), pool.port(), zmq_buf, tlsVersion ? tlsVersion : "", client->ip().data()); const char *fingerprint = client->tlsFingerprint(); if (fingerprint != nullptr) { @@ -272,8 +277,13 @@ void xmrig::Network::setJob(IClient *client, const Job &job, bool donate) uint64_t diff = job.diff();; const char *scale = NetworkState::scaleDiff(diff); - LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), - Tags::network(), client->pool().host().data(), client->pool().port(), diff, scale, job.algorithm().shortName(), job.height()); + char zmq_buf[32] = {}; + if (client->pool().zmq_port() >= 0) { + snprintf(zmq_buf, sizeof(zmq_buf), " (ZMQ:%d)", client->pool().zmq_port()); + } + + LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d%s") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), + Tags::network(), client->pool().host().data(), client->pool().port(), zmq_buf, diff, scale, job.algorithm().shortName(), job.height()); } if (!donate && m_donate) { From d24581c9633cb60c3c588975a32bc969e7c6a5b3 Mon Sep 17 00:00:00 2001 From: XMRig <support@xmrig.com> Date: Sat, 24 Jul 2021 12:27:48 +0700 Subject: [PATCH 6/8] #2492 Add missing --huge-pages-jit command line option. --- src/base/kernel/interfaces/IConfig.h | 1 + src/core/config/ConfigTransform.cpp | 3 +++ src/core/config/Config_platform.h | 2 ++ src/core/config/usage.h | 3 +++ 4 files changed, 9 insertions(+) diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index e531353aa..bc4607865 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -86,6 +86,7 @@ public: DnsTtlKey = 1054, SpendSecretKey = 1055, DaemonZMQPortKey = 1056, + HugePagesJitKey = 1057, // xmrig common CPUPriorityKey = 1021, diff --git a/src/core/config/ConfigTransform.cpp b/src/core/config/ConfigTransform.cpp index c854d982a..1c4f4244a 100644 --- a/src/core/config/ConfigTransform.cpp +++ b/src/core/config/ConfigTransform.cpp @@ -195,6 +195,9 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const case IConfig::RandomXCacheQoSKey: /* --cache-qos */ return set(doc, RxConfig::kField, RxConfig::kCacheQoS, true); + + case IConfig::HugePagesJitKey: /* --huge-pages-jit */ + return set(doc, CpuConfig::kField, CpuConfig::kHugePagesJit, true); # endif # ifdef XMRIG_FEATURE_OPENCL diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index 7194f5cc5..c4379d0b4 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -69,6 +69,8 @@ static const option options[] = { { "no-huge-pages", 0, nullptr, IConfig::HugePagesKey }, { "no-hugepages", 0, nullptr, IConfig::HugePagesKey }, { "hugepage-size", 1, nullptr, IConfig::HugePageSizeKey }, + { "huge-pages-jit", 0, nullptr, IConfig::HugePagesJitKey }, + { "hugepages-jit", 0, nullptr, IConfig::HugePagesJitKey }, { "pass", 1, nullptr, IConfig::PasswordKey }, { "print-time", 1, nullptr, IConfig::PrintTimeKey }, { "retries", 1, nullptr, IConfig::RetriesKey }, diff --git a/src/core/config/usage.h b/src/core/config/usage.h index 4230c9e2f..6cd599c96 100644 --- a/src/core/config/usage.h +++ b/src/core/config/usage.h @@ -88,6 +88,9 @@ static inline const std::string &usage() u += " --no-huge-pages disable huge pages support\n"; # ifdef XMRIG_OS_LINUX u += " --hugepage-size=N custom hugepage size in kB\n"; +# endif +# ifdef XMRIG_ALGO_RANDOMX + u += " --huge-pages-jit enable huge pages support for RandomX JIT code\n"; # endif u += " --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer\n"; From 929205536c6d74e3eb86694a79dc15ed8fd19249 Mon Sep 17 00:00:00 2001 From: SChernykh <sergey.v.chernykh@gmail.com> Date: Sat, 7 Aug 2021 19:38:31 +0200 Subject: [PATCH 7/8] Show the number of transactions in pool job Useful to check if pool/proxy is working properly and can also be used to compare different pools. --- src/base/net/stratum/Job.cpp | 25 +++++++++++++++++++++++++ src/base/net/stratum/Job.h | 2 ++ src/net/Network.cpp | 12 +++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index 920bf95f7..7792b904a 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -163,6 +163,31 @@ void xmrig::Job::setSigKey(const char *sig_key) } +uint32_t xmrig::Job::getNumTransactions() const +{ + if (m_algorithm.family() > Algorithm::RANDOM_X) { + return 0; + } + + uint32_t num_transactions = 0; + + // Monero (and some other coins) has the number of transactions encoded as varint in the end of hashing blob + const size_t expected_tx_offset = (m_algorithm == Algorithm::RX_WOW) ? 141 : 75; + + if ((m_size > expected_tx_offset) && (m_size <= expected_tx_offset + 4)) { + for (size_t i = expected_tx_offset, k = 0; i < m_size; ++i, k += 7) { + const uint8_t b = m_blob[i]; + num_transactions |= static_cast<uint32_t>(b & 0x7F) << k; + if ((b & 0x80) == 0) { + break; + } + } + } + + return num_transactions; +} + + void xmrig::Job::copy(const Job &other) { m_algorithm = other.m_algorithm; diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index c72902756..414da8fea 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -139,6 +139,8 @@ public: inline bool hasMinerSignature() const { return m_hasMinerSignature; } + uint32_t getNumTransactions() const; + private: void copy(const Job &other); void move(Job &&other); diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 64a1b689e..d1acb4ce4 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -274,7 +274,7 @@ void xmrig::Network::setJob(IClient *client, const Job &job, bool donate) if (!BenchState::size()) # endif { - uint64_t diff = job.diff();; + uint64_t diff = job.diff(); const char *scale = NetworkState::scaleDiff(diff); char zmq_buf[32] = {}; @@ -282,8 +282,14 @@ void xmrig::Network::setJob(IClient *client, const Job &job, bool donate) snprintf(zmq_buf, sizeof(zmq_buf), " (ZMQ:%d)", client->pool().zmq_port()); } - LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d%s") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64), - Tags::network(), client->pool().host().data(), client->pool().port(), zmq_buf, diff, scale, job.algorithm().shortName(), job.height()); + char tx_buf[32] = {}; + const uint32_t num_transactions = job.getNumTransactions(); + if (num_transactions > 0) { + snprintf(tx_buf, sizeof(tx_buf), " (%u tx)", num_transactions); + } + + LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d%s") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64) "%s", + Tags::network(), client->pool().host().data(), client->pool().port(), zmq_buf, diff, scale, job.algorithm().shortName(), job.height(), tx_buf); } if (!donate && m_donate) { From 08d79ddcdc350e5531ea9d27a2815529250cb467 Mon Sep 17 00:00:00 2001 From: XMRig <support@xmrig.com> Date: Sun, 8 Aug 2021 19:36:54 +0700 Subject: [PATCH 8/8] v6.14.0-dev --- CHANGELOG.md | 6 ++++++ src/version.h | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1f4b4612..4482cc44e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v6.14.0 +- [#2484](https://github.com/xmrig/xmrig/pull/2484) Added ZeroMQ support for solo mining. +- [#2476](https://github.com/xmrig/xmrig/issues/2476) Fixed crash in DMI memory reader. +- [#2492](https://github.com/xmrig/xmrig/issues/2492) Added missing `--huge-pages-jit` command line option. +- [#2512](https://github.com/xmrig/xmrig/pull/2512) Added show the number of transactions in pool job. + # v6.13.1 - [#2468](https://github.com/xmrig/xmrig/pull/2468) Fixed regression in previous version: don't send miner signature during regular mining. diff --git a/src/version.h b/src/version.h index 5dfc7b2b7..3d523fee4 100644 --- a/src/version.h +++ b/src/version.h @@ -28,15 +28,15 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig miner" -#define APP_VERSION "6.13.2-dev" +#define APP_VERSION "6.14.0-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2021 xmrig.com" #define APP_KIND "miner" #define APP_VER_MAJOR 6 -#define APP_VER_MINOR 13 -#define APP_VER_PATCH 2 +#define APP_VER_MINOR 14 +#define APP_VER_PATCH 0 #ifdef _MSC_VER # if (_MSC_VER >= 1920)