diff --git a/CHANGELOG.md b/CHANGELOG.md index 773a56c5b..4910d5ef3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v6.19.2 +- [#3230](https://github.com/xmrig/xmrig/pull/3230) Fixed parsing of `TX_EXTRA_MERGE_MINING_TAG`. +- [#3232](https://github.com/xmrig/xmrig/pull/3232) Added new `X-Hash-Difficulty` HTTP header. +- [#3240](https://github.com/xmrig/xmrig/pull/3240) Improved .cmd files when run by shortcuts on another drive. +- [#3241](https://github.com/xmrig/xmrig/pull/3241) Added view tag calculation (fixes Wownero solo mining issue). + # v6.19.1 - Resolved deprecated methods warnings with OpenSSL 3.0. - [#3213](https://github.com/xmrig/xmrig/pull/3213) Fixed build with 32-bit clang 15. diff --git a/scripts/benchmark_10M.cmd b/scripts/benchmark_10M.cmd index dbbcc78c2..833f065cd 100644 --- a/scripts/benchmark_10M.cmd +++ b/scripts/benchmark_10M.cmd @@ -1,4 +1,4 @@ @echo off -cd %~dp0 +cd /d "%~dp0" xmrig.exe --bench=10M --submit pause diff --git a/scripts/benchmark_1M.cmd b/scripts/benchmark_1M.cmd index 5d2166d0c..b106a1bc8 100644 --- a/scripts/benchmark_1M.cmd +++ b/scripts/benchmark_1M.cmd @@ -1,4 +1,4 @@ @echo off -cd %~dp0 +cd /d "%~dp0" xmrig.exe --bench=1M --submit pause diff --git a/scripts/pool_mine_example.cmd b/scripts/pool_mine_example.cmd index 6e35c913f..41a42340f 100644 --- a/scripts/pool_mine_example.cmd +++ b/scripts/pool_mine_example.cmd @@ -15,6 +15,6 @@ :: Choose pools outside of top 5 to help Monero network be more decentralized! :: Smaller pools also often have smaller fees/payout limits. -cd %~dp0 +cd /d "%~dp0" xmrig.exe -o pool.hashvault.pro:3333 -u 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD -p x pause diff --git a/scripts/rtm_ghostrider_example.cmd b/scripts/rtm_ghostrider_example.cmd index 8b1f4999c..85e0a7fbf 100644 --- a/scripts/rtm_ghostrider_example.cmd +++ b/scripts/rtm_ghostrider_example.cmd @@ -15,7 +15,7 @@ :: Choose pools outside of top 5 to help Raptoreum network be more decentralized! :: Smaller pools also often have smaller fees/payout limits. -cd %~dp0 +cd /d "%~dp0" :: Use this command line to connect to non-SSL port xmrig.exe -a gr -o raptoreumemporium.com:3008 -u WALLET_ADDRESS -p x :: Or use this command line to connect to an SSL port diff --git a/scripts/solo_mine_example.cmd b/scripts/solo_mine_example.cmd index c925b36d9..4cebf5673 100644 --- a/scripts/solo_mine_example.cmd +++ b/scripts/solo_mine_example.cmd @@ -11,6 +11,6 @@ :: Mining solo is the best way to help Monero network be more decentralized! :: But you will only get a payout when you find a block which can take more than a year for a single low-end PC. -cd %~dp0 +cd /d "%~dp0" xmrig.exe -o node.xmr.to:18081 -a rx/0 -u 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD --daemon pause diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 10c041163..9b1cdc425 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -148,6 +148,11 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result) memcpy(data + sig_offset * 2, result.sig, 64 * 2); memcpy(data + m_blocktemplate.offset(BlockTemplate::TX_PUBKEY_OFFSET) * 2, result.sig_data, 32 * 2); memcpy(data + m_blocktemplate.offset(BlockTemplate::EPH_PUBLIC_KEY_OFFSET) * 2, result.sig_data + 32 * 2, 32 * 2); + + // Handle view tag for txout_to_tagged_key outputs + if (m_blocktemplate.outputType() == 3) { + Cvt::toHex(data + m_blocktemplate.offset(BlockTemplate::EPH_PUBLIC_KEY_OFFSET) * 2 + 32 * 2, 2, &result.view_tag, 1); + } } if (result.extra_nonce >= 0) { @@ -178,7 +183,10 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result) m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), 0, result.backend); # endif - return rpcSend(doc); + std::map headers; + headers.insert({"X-Hash-Difficulty", std::to_string(result.actualDiff())}); + + return rpcSend(doc, headers); } @@ -401,7 +409,8 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) m_blocktemplate.offset(BlockTemplate::TX_PUBKEY_OFFSET) - k, m_blocktemplate.offset(BlockTemplate::TX_EXTRA_NONCE_OFFSET) - k, m_blocktemplate.txExtraNonce().size(), - m_blocktemplate.minerTxMerkleTreeBranch() + m_blocktemplate.minerTxMerkleTreeBranch(), + m_blocktemplate.outputType() == 3 ); # endif @@ -438,7 +447,7 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) } uint8_t derivation[32]; - if (!generate_key_derivation(m_blocktemplate.blob(BlockTemplate::TX_PUBKEY_OFFSET), secret_viewkey, derivation)) { + if (!generate_key_derivation(m_blocktemplate.blob(BlockTemplate::TX_PUBKEY_OFFSET), secret_viewkey, derivation, nullptr)) { return jobError("Failed to generate key derivation for miner signature."); } @@ -553,9 +562,13 @@ int64_t xmrig::DaemonClient::getBlockTemplate() } -int64_t xmrig::DaemonClient::rpcSend(const rapidjson::Document &doc) +int64_t xmrig::DaemonClient::rpcSend(const rapidjson::Document &doc, const std::map &headers) { FetchRequest req(HTTP_POST, m_pool.host(), m_pool.port(), kJsonRPC, doc, m_pool.isTLS(), isQuiet()); + for (const auto &header : headers) { + req.headers.insert(header); + } + fetch(tag(), std::move(req), m_httpListener); return m_sequence++; diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index 94d2b973a..e852f428c 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -86,7 +86,7 @@ private: bool parseJob(const rapidjson::Value ¶ms, int *code); bool parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error); int64_t getBlockTemplate(); - int64_t rpcSend(const rapidjson::Document &doc); + int64_t rpcSend(const rapidjson::Document &doc, const std::map &headers = {}); void retry(); void send(const char *path); void setState(SocketState state); diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index 56f5de804..d62e00b1d 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -245,6 +245,7 @@ void xmrig::Job::copy(const Job &other) m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset; m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize; m_minerTxMerkleTreeBranch = other.m_minerTxMerkleTreeBranch; + m_hasViewTag = other.m_hasViewTag; # else memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey)); memcpy(m_ephSecretKey, other.m_ephSecretKey, sizeof(m_ephSecretKey)); @@ -300,6 +301,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_hasViewTag = other.m_hasViewTag; # else memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey)); memcpy(m_ephSecretKey, other.m_ephSecretKey, sizeof(m_ephSecretKey)); @@ -323,7 +325,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) +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) { m_minerTxPrefix.assign(begin, end); m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset; @@ -331,6 +333,13 @@ 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_hasViewTag = hasViewTag; +} + + +void xmrig::Job::setViewTagInMinerTx(uint8_t view_tag) +{ + memcpy(m_minerTxPrefix.data() + m_minerTxEphPubKeyOffset + 32, &view_tag, 1); } @@ -340,7 +349,7 @@ void xmrig::Job::setExtraNonceInMinerTx(uint32_t extra_nonce) } -void xmrig::Job::generateSignatureData(String &signatureData) const +void xmrig::Job::generateSignatureData(String &signatureData, uint8_t& view_tag) const { uint8_t* eph_public_key = m_minerTxPrefix.data() + m_minerTxEphPubKeyOffset; uint8_t* txkey_pub = m_minerTxPrefix.data() + m_minerTxPubKeyOffset; @@ -351,14 +360,14 @@ void xmrig::Job::generateSignatureData(String &signatureData) const uint8_t derivation[32]; - generate_key_derivation(m_viewPublicKey, txkey_sec, derivation); + generate_key_derivation(m_viewPublicKey, txkey_sec, derivation, &view_tag); derive_public_key(derivation, 0, m_spendPublicKey, eph_public_key); uint8_t buf[32 * 3] = {}; memcpy(buf, txkey_pub, 32); memcpy(buf + 32, eph_public_key, 32); - generate_key_derivation(txkey_pub, m_viewSecretKey, derivation); + generate_key_derivation(txkey_pub, m_viewSecretKey, derivation, nullptr); derive_secret_key(derivation, 0, m_spendSecretKey, buf + 64); signatureData = Cvt::toHex(buf, sizeof(buf)); diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index e314a266d..1ecff3692 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -120,10 +120,13 @@ public: # endif # ifdef XMRIG_PROXY_PROJECT + 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); + 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 setViewTagInMinerTx(uint8_t view_tag); void setExtraNonceInMinerTx(uint32_t extra_nonce); - void generateSignatureData(String& signatureData) const; + void generateSignatureData(String& signatureData, uint8_t& view_tag) const; void generateHashingBlob(String& blob) const; # else inline const uint8_t* ephSecretKey() const { return m_hasMinerSignature ? m_ephSecretKey : nullptr; } @@ -178,6 +181,7 @@ private: size_t m_minerTxExtraNonceOffset = 0; size_t m_minerTxExtraNonceSize = 0; Buffer m_minerTxMerkleTreeBranch; + bool m_hasViewTag = false; # else // Miner signatures uint8_t m_ephPublicKey[32]{}; diff --git a/src/base/tools/cryptonote/BlockTemplate.cpp b/src/base/tools/cryptonote/BlockTemplate.cpp index b4fe4bcf4..6ce49679e 100644 --- a/src/base/tools/cryptonote/BlockTemplate.cpp +++ b/src/base/tools/cryptonote/BlockTemplate.cpp @@ -269,7 +269,7 @@ bool xmrig::BlockTemplate::parse(bool hashes) case 0x03: // TX_EXTRA_MERGE_MINING_TAG ar_extra(size); setOffset(TX_EXTRA_MERGE_MINING_TAG_OFFSET, offset(TX_EXTRA_OFFSET) + ar_extra.index()); - ar_extra(m_txMergeMiningTag, size + kKeySize); + ar_extra(m_txMergeMiningTag, size); break; default: diff --git a/src/base/tools/cryptonote/Signatures.cpp b/src/base/tools/cryptonote/Signatures.cpp index 935712585..13f0c9485 100644 --- a/src/base/tools/cryptonote/Signatures.cpp +++ b/src/base/tools/cryptonote/Signatures.cpp @@ -147,7 +147,7 @@ bool check_signature(const uint8_t* prefix_hash, const uint8_t* pub, const uint8 } -bool generate_key_derivation(const uint8_t* key1, const uint8_t* key2, uint8_t* derivation) +bool generate_key_derivation(const uint8_t* key1, const uint8_t* key2, uint8_t* derivation, uint8_t* view_tag) { ge_p3 point; ge_p2 point2; @@ -162,6 +162,22 @@ bool generate_key_derivation(const uint8_t* key1, const uint8_t* key2, uint8_t* ge_p1p1_to_p2(&point2, &point3); ge_tobytes(derivation, &point2); + if (view_tag) { + constexpr uint8_t salt[] = "view_tag"; + constexpr size_t SALT_SIZE = sizeof(salt) - 1; + + uint8_t buf[SALT_SIZE + 32 + 1]; + memcpy(buf, salt, SALT_SIZE); + memcpy(buf + SALT_SIZE, derivation, 32); + + // Assuming output_index == 0 + buf[SALT_SIZE + 32] = 0; + + uint8_t view_tag_full[32]; + xmrig::keccak(buf, sizeof(buf), view_tag_full, sizeof(view_tag_full)); + *view_tag = view_tag_full[0]; + } + return true; } diff --git a/src/base/tools/cryptonote/Signatures.h b/src/base/tools/cryptonote/Signatures.h index 048133139..24ea9ac62 100644 --- a/src/base/tools/cryptonote/Signatures.h +++ b/src/base/tools/cryptonote/Signatures.h @@ -31,7 +31,7 @@ namespace xmrig { void generate_signature(const uint8_t* prefix_hash, const uint8_t* pub, const uint8_t* sec, uint8_t* sig); bool check_signature(const uint8_t* prefix_hash, const uint8_t* pub, const uint8_t* sig); -bool generate_key_derivation(const uint8_t* key1, const uint8_t* key2, uint8_t* derivation); +bool generate_key_derivation(const uint8_t* key1, const uint8_t* key2, uint8_t* derivation, uint8_t* view_tag); void derive_secret_key(const uint8_t* derivation, size_t output_index, const uint8_t* base, uint8_t* derived_key); bool derive_public_key(const uint8_t* derivation, size_t output_index, const uint8_t* base, uint8_t* derived_key); diff --git a/src/version.h b/src/version.h index 78e3589aa..7b865fe7b 100644 --- a/src/version.h +++ b/src/version.h @@ -22,7 +22,7 @@ #define APP_ID "xmrig" #define APP_NAME "XMRig" #define APP_DESC "XMRig miner" -#define APP_VERSION "6.19.1" +#define APP_VERSION "6.19.2-dev" #define APP_DOMAIN "xmrig.com" #define APP_SITE "www.xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2023 xmrig.com" @@ -30,7 +30,7 @@ #define APP_VER_MAJOR 6 #define APP_VER_MINOR 19 -#define APP_VER_PATCH 1 +#define APP_VER_PATCH 2 #ifdef _MSC_VER # if (_MSC_VER >= 1930)