diff --git a/CMakeLists.txt b/CMakeLists.txt index 967f5007..0171add3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ option(WITH_ARGON2 "Enable Argon2 algorithms family" ON) option(WITH_ASTROBWT "Enable AstroBWT algorithms family" ON) option(WITH_KAWPOW "Enable KawPow algorithms family" ON) option(WITH_HTTP "Enable HTTP protocol support (client/server)" ON) -option(WITH_DEBUG_LOG "Enable debug log output" ON) +option(WITH_DEBUG_LOG "Enable debug log output" OFF) option(WITH_TLS "Enable OpenSSL support" ON) option(WITH_ASM "Enable ASM PoW implementations" ON) option(WITH_MSR "Enable MSR mod & 1st-gen Ryzen fix" ON) diff --git a/src/backend/common/WorkerJob.h b/src/backend/common/WorkerJob.h index cf664f87..8ff3ccdc 100644 --- a/src/backend/common/WorkerJob.h +++ b/src/backend/common/WorkerJob.h @@ -85,9 +85,10 @@ public: } + inline int32_t nonceOffset() const { return currentJob().nonceOffset(); } + inline size_t nonceSize() const { return currentJob().nonceSize(); } + private: - inline int32_t nonceOffset() const { return currentJob().nonceOffset(); } - inline size_t nonceSize() const { return currentJob().nonceSize(); } inline uint64_t nonceMask() const { return m_nonce_mask[index()]; } inline void save(const Job &job, uint32_t reserveCount, Nonce::Backend backend) diff --git a/src/backend/cpu/CpuWorker.cpp b/src/backend/cpu/CpuWorker.cpp index 9ffc5ea5..becc329b 100644 --- a/src/backend/cpu/CpuWorker.cpp +++ b/src/backend/cpu/CpuWorker.cpp @@ -274,10 +274,16 @@ void xmrig::CpuWorker::start() bool valid = true; + uint8_t miner_signature_saved[64]; + uint8_t* miner_signature_ptr = m_job.blob() + m_job.nonceOffset() + m_job.nonceSize(); + # ifdef XMRIG_ALGO_RANDOMX if (job.algorithm().family() == Algorithm::RANDOM_X) { if (first) { first = false; + if (job.hasMinerSignature()) { + job.generateMinerSignature(m_job.currentJob().timestamp() + *m_job.nonce(), miner_signature_ptr); + } randomx_calculate_hash_first(m_vm, tempHash, m_job.blob(), job.size()); } @@ -285,6 +291,10 @@ void xmrig::CpuWorker::start() break; } + if (job.hasMinerSignature()) { + memcpy(miner_signature_saved, miner_signature_ptr, sizeof(miner_signature_saved)); + job.generateMinerSignature(m_job.currentJob().timestamp() + *m_job.nonce(), miner_signature_ptr); + } randomx_calculate_hash_next(m_vm, tempHash, m_job.blob(), job.size(), m_hash); } else @@ -319,7 +329,7 @@ void xmrig::CpuWorker::start() else # endif if (value < job.target()) { - JobResults::submit(job, current_job_nonces[i], m_hash + (i * 32)); + JobResults::submit(job, current_job_nonces[i], m_hash + (i * 32), miner_signature_saved); } } m_count += N; diff --git a/src/base/crypto/Coin.cpp b/src/base/crypto/Coin.cpp index 33115484..a70ca075 100644 --- a/src/base/crypto/Coin.cpp +++ b/src/base/crypto/Coin.cpp @@ -56,7 +56,8 @@ static CoinName const coin_names[] = { { "ravencoin", Coin::RAVEN }, { "raven", Coin::RAVEN }, { "rvn", Coin::RAVEN }, - { "conceal", Coin::CONCEAL } + { "conceal", Coin::CONCEAL }, + { "wownero", Coin::WOWNERO } }; @@ -85,6 +86,9 @@ xmrig::Algorithm::Id xmrig::Coin::algorithm(uint8_t blobVersion) const case CONCEAL: return Algorithm::CN_CCX; + case WOWNERO: + return Algorithm::RX_WOW; + case INVALID: break; } diff --git a/src/base/crypto/Coin.h b/src/base/crypto/Coin.h index 084672fc..985335cb 100644 --- a/src/base/crypto/Coin.h +++ b/src/base/crypto/Coin.h @@ -44,7 +44,8 @@ public: DERO, KEVA, RAVEN, - CONCEAL + CONCEAL, + WOWNERO }; diff --git a/src/base/kernel/config/BaseTransform.cpp b/src/base/kernel/config/BaseTransform.cpp index 3cd48d5a..1036ae29 100644 --- a/src/base/kernel/config/BaseTransform.cpp +++ b/src/base/kernel/config/BaseTransform.cpp @@ -181,6 +181,9 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch case IConfig::PasswordKey: /* --pass */ return add(doc, Pools::kPools, Pool::kPass, arg); + case IConfig::SpendSecretKey: /* --spend-secret-key */ + return add(doc, Pools::kPools, Pool::kSpendSecretKey, arg); + case IConfig::RigIdKey: /* --rig-id */ return add(doc, Pools::kPools, Pool::kRigId, arg); diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h index ec3d8510..d1260afa 100644 --- a/src/base/kernel/interfaces/IConfig.h +++ b/src/base/kernel/interfaces/IConfig.h @@ -84,6 +84,7 @@ public: SubmitToOriginKey = 1052, DnsIPv6Key = 1053, DnsTtlKey = 1054, + SpendSecretKey = 1055, // xmrig common CPUPriorityKey = 1021, diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index 5bfe095c..97a0d219 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -37,6 +37,7 @@ #include "base/net/stratum/SubmitResult.h" #include "base/tools/Cvt.h" #include "base/tools/Timer.h" +#include "base/tools/cryptonote/Signatures.h" #include "net/JobResult.h" @@ -94,11 +95,11 @@ bool xmrig::DaemonClient::isTLS() const int64_t xmrig::DaemonClient::submit(const JobResult &result) { - if (result.jobId != (m_blocktemplate.data() + m_blocktemplate.size() - 32)) { + if (result.jobId != (m_blocktemplateStr.data() + m_blocktemplateStr.size() - 32)) { return -1; } - char *data = (m_apiVersion == API_DERO) ? m_blockhashingblob.data() : m_blocktemplate.data(); + char *data = (m_apiVersion == API_DERO) ? m_blockhashingblob.data() : m_blocktemplateStr.data(); # ifdef XMRIG_PROXY_PROJECT memcpy(data + 78, result.nonce, 8); @@ -106,16 +107,21 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result) Cvt::toHex(data + 78, 8, reinterpret_cast(&result.nonce), 4); # endif + if (m_blocktemplate.has_miner_signature) { + const size_t sig_offset = m_job.nonceOffset() + m_job.nonceSize(); + Cvt::toHex(data + sig_offset * 2, 128, result.minerSignature(), 64); + } + using namespace rapidjson; Document doc(kObjectType); Value params(kArrayType); if (m_apiVersion == API_DERO) { - params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator()); + params.PushBack(m_blocktemplateStr.toJSON(), doc.GetAllocator()); params.PushBack(m_blockhashingblob.toJSON(), doc.GetAllocator()); } else { - params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator()); + params.PushBack(m_blocktemplateStr.toJSON(), doc.GetAllocator()); } JsonRequest::create(doc, m_sequence, "submitblock", params); @@ -263,9 +269,53 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) job.setDiff(Json::getUint64(params, "difficulty")); job.setId(blocktemplate.data() + blocktemplate.size() - 32); - m_job = std::move(job); - m_blocktemplate = std::move(blocktemplate); - m_prevHash = Json::getString(params, "prev_hash"); + Coin pool_coin = m_pool.coin(); + + if ((pool_coin == Coin::INVALID) && (m_pool.algorithm() == Algorithm::RX_WOW)) { + pool_coin = Coin::WOWNERO; + } + + if (!m_blocktemplate.Init(blocktemplate, pool_coin)) { + LOG_ERR("Invalid block template received from daemon"); + return false; + } + + if (m_blocktemplate.has_miner_signature) { + if (m_pool.spendSecretKey().isEmpty()) { + LOG_ERR("Secret spend key is not set"); + return false; + } + + if (m_pool.spendSecretKey().size() != 64) { + LOG_ERR("Secret spend key has invalid length. It must be 64 hex characters."); + return false; + } + + uint8_t secret_spendkey[32]; + if (!Cvt::fromHex(secret_spendkey, 32, m_pool.spendSecretKey(), 64)) { + LOG_ERR("Secret spend key is not a valid hex data."); + return false; + } + + uint8_t secret_viewkey[32]; + derive_view_secret_key(secret_spendkey, secret_viewkey); + + uint8_t derivation[32]; + if (!generate_key_derivation(m_blocktemplate.raw_blob.data() + m_blocktemplate.tx_pubkey_index, secret_viewkey, derivation)) { + LOG_ERR("Failed to generate key derivation for miner signature."); + return false; + } + + uint8_t eph_secret_key[32]; + derive_secret_key(derivation, 0, secret_spendkey, eph_secret_key); + + job.setEphemeralKeys(m_blocktemplate.raw_blob.data() + m_blocktemplate.eph_public_key_index, eph_secret_key); + job.setTimestamp(m_blocktemplate.timestamp); + } + + m_job = std::move(job); + m_blocktemplateStr = std::move(blocktemplate); + m_prevHash = Json::getString(params, "prev_hash"); if (m_apiVersion == API_DERO) { // Truncate to 32 bytes to have the same data as in get_info RPC diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index ff4f9e04..45a84464 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -31,6 +31,7 @@ #include "base/kernel/interfaces/ITimerListener.h" #include "base/net/stratum/BaseClient.h" #include "base/tools/Object.h" +#include "base/tools/cryptonote/BlockTemplate.h" #include @@ -83,7 +84,7 @@ private: } m_apiVersion = API_MONERO; std::shared_ptr m_httpListener; - String m_blocktemplate; + String m_blocktemplateStr; String m_blockhashingblob; String m_prevHash; String m_tlsFingerprint; @@ -91,6 +92,8 @@ private: Timer *m_timer; uint64_t m_blocktemplateRequestHeight = 0; String m_blocktemplateRequestHash; + + BlockTemplate m_blocktemplate; }; diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp index 134a5064..d429b98e 100644 --- a/src/base/net/stratum/Job.cpp +++ b/src/base/net/stratum/Job.cpp @@ -32,6 +32,8 @@ #include "base/net/stratum/Job.h" #include "base/tools/Buffer.h" #include "base/tools/Cvt.h" +#include "base/tools/cryptonote/Signatures.h" +#include "base/crypto/keccak.h" xmrig::Job::Job(bool nicehash, const Algorithm &algorithm, const String &clientId) : @@ -169,6 +171,13 @@ void xmrig::Job::copy(const Job &other) # ifdef XMRIG_FEATURE_BENCHMARK m_benchSize = other.m_benchSize; # endif + + m_hasMinerSignature = other.m_hasMinerSignature; + + memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey)); + memcpy(m_ephSecretKey, other.m_ephSecretKey, sizeof(m_ephSecretKey)); + + m_timestamp = other.m_timestamp; } @@ -204,4 +213,27 @@ void xmrig::Job::move(Job &&other) # ifdef XMRIG_FEATURE_BENCHMARK m_benchSize = other.m_benchSize; # endif + + m_hasMinerSignature = other.m_hasMinerSignature; + + memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey)); + memcpy(m_ephSecretKey, other.m_ephSecretKey, sizeof(m_ephSecretKey)); + + m_timestamp = other.m_timestamp; +} + + +void xmrig::Job::generateMinerSignature(uint64_t data, uint8_t* sig) const +{ + uint8_t sig_data[16]; + int k = sizeof(sig_data); + do { + sig_data[--k] = "0123456789"[data % 10]; + data /= 10; + } while (data); + + uint8_t prefix_hash[32]; + xmrig::keccak(sig_data + k, sizeof(sig_data) - k, prefix_hash, sizeof(prefix_hash)); + + xmrig::generate_signature(prefix_hash, m_ephPublicKey, m_ephSecretKey, sig); } diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h index 5621cbc7..047e9b15 100644 --- a/src/base/net/stratum/Job.h +++ b/src/base/net/stratum/Job.h @@ -116,6 +116,21 @@ public: inline void setBenchSize(uint32_t size) { m_benchSize = size; } # endif + inline const uint8_t* ephSecretKey() const { return m_hasMinerSignature ? m_ephSecretKey : nullptr; } + inline uint64_t timestamp() const { return m_timestamp; } + + inline void setEphemeralKeys(uint8_t* pub_key, uint8_t* sec_key) + { + m_hasMinerSignature = true; + memcpy(m_ephPublicKey, pub_key, sizeof(m_ephSecretKey)); + memcpy(m_ephSecretKey, sec_key, sizeof(m_ephSecretKey)); + } + + inline void setTimestamp(uint64_t timestamp) { m_timestamp = timestamp; } + + inline bool hasMinerSignature() const { return m_hasMinerSignature; } + void generateMinerSignature(uint64_t data, uint8_t* sig) const; + private: void copy(const Job &other); void move(Job &&other); @@ -144,6 +159,11 @@ private: # ifdef XMRIG_FEATURE_BENCHMARK uint32_t m_benchSize = 0; # endif + + bool m_hasMinerSignature = false; + uint8_t m_ephPublicKey[32]{}; + uint8_t m_ephSecretKey[32]{}; + uint64_t m_timestamp = 0; }; diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index e39df3b5..86e3205e 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -78,6 +78,7 @@ const char *Pool::kSubmitToOrigin = "submit-to-origin"; const char *Pool::kTls = "tls"; const char *Pool::kUrl = "url"; const char *Pool::kUser = "user"; +const char *Pool::kSpendSecretKey = "spend-secret-key"; const char *Pool::kNicehashHost = "nicehash.com"; @@ -92,12 +93,13 @@ xmrig::Pool::Pool(const char *url) : } -xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls, Mode mode) : +xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, const char* spendSecretKey, int keepAlive, bool nicehash, bool tls, Mode mode) : m_keepAlive(keepAlive), m_mode(mode), m_flags(1 << FLAG_ENABLED), m_password(password), m_user(user), + m_spendSecretKey(spendSecretKey), m_pollInterval(kDefaultPollInterval), m_url(host, port, tls) { @@ -115,15 +117,16 @@ xmrig::Pool::Pool(const rapidjson::Value &object) : return; } - m_user = Json::getString(object, kUser); - m_password = Json::getString(object, kPass); - m_rigId = Json::getString(object, kRigId); - m_fingerprint = Json::getString(object, kFingerprint); - m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval); - m_algorithm = Json::getString(object, kAlgo); - m_coin = Json::getString(object, kCoin); - m_daemon = Json::getString(object, kSelfSelect); - m_proxy = Json::getValue(object, kSOCKS5); + m_user = Json::getString(object, kUser); + m_spendSecretKey = Json::getString(object, kSpendSecretKey); + m_password = Json::getString(object, kPass); + m_rigId = Json::getString(object, kRigId); + m_fingerprint = Json::getString(object, kFingerprint); + m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval); + m_algorithm = Json::getString(object, kAlgo); + m_coin = Json::getString(object, kCoin); + m_daemon = Json::getString(object, kSelfSelect); + m_proxy = Json::getValue(object, kSOCKS5); m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true)); m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash) || m_url.host().contains(kNicehashHost)); @@ -270,6 +273,10 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const obj.AddMember(StringRef(kUrl), url().toJSON(), allocator); obj.AddMember(StringRef(kUser), m_user.toJSON(), allocator); + if (!m_spendSecretKey.isEmpty()) { + obj.AddMember(StringRef(kSpendSecretKey), m_spendSecretKey.toJSON(), allocator); + } + if (m_mode != MODE_DAEMON) { obj.AddMember(StringRef(kPass), m_password.toJSON(), allocator); obj.AddMember(StringRef(kRigId), m_rigId.toJSON(), allocator); diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h index 3f9baecf..c7abbbf3 100644 --- a/src/base/net/stratum/Pool.h +++ b/src/base/net/stratum/Pool.h @@ -71,6 +71,7 @@ public: static const char *kTls; static const char *kUrl; static const char *kUser; + static const char* kSpendSecretKey; static const char *kNicehashHost; constexpr static int kKeepAliveTimeout = 60; @@ -78,7 +79,7 @@ public: constexpr static uint64_t kDefaultPollInterval = 1000; Pool() = default; - Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls, Mode mode); + Pool(const char *host, uint16_t port, const char *user, const char *password, const char* spendSecretKey, int keepAlive, bool nicehash, bool tls, Mode mode); Pool(const char *url); Pool(const rapidjson::Value &object); @@ -101,6 +102,7 @@ public: inline const String &rigId() const { return m_rigId; } inline const String &url() const { return m_url.url(); } inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; } + inline const String &spendSecretKey() const { return m_spendSecretKey; } inline const Url &daemon() const { return m_daemon; } inline int keepAlive() const { return m_keepAlive; } inline Mode mode() const { return m_mode; } @@ -149,6 +151,7 @@ private: String m_password; String m_rigId; String m_user; + String m_spendSecretKey; uint64_t m_pollInterval = kDefaultPollInterval; Url m_daemon; Url m_url; diff --git a/src/base/tools/cryptonote/BlockTemplate.cpp b/src/base/tools/cryptonote/BlockTemplate.cpp index 6980eb04..80dd6796 100644 --- a/src/base/tools/cryptonote/BlockTemplate.cpp +++ b/src/base/tools/cryptonote/BlockTemplate.cpp @@ -28,7 +28,7 @@ namespace xmrig { -bool CBlockTemplate::Init(const String& blockTemplate) +bool BlockTemplate::Init(const String& blockTemplate, Coin coin) { raw_blob = Cvt::fromHex(blockTemplate); @@ -41,6 +41,12 @@ bool CBlockTemplate::Init(const String& blockTemplate) ar(prev_id); ar(nonce); + // Wownero block template has miner signature starting from version 19 + has_miner_signature = (coin == Coin::WOWNERO) && (major_version >= 19); + if (has_miner_signature) { + ar(miner_signature); + } + // Miner transaction begin // Prefix begin miner_tx_prefix_begin_index = ar.index(); @@ -108,7 +114,7 @@ bool CBlockTemplate::Init(const String& blockTemplate) ar(num_hashes); hashes.resize((num_hashes + 1) * HASH_SIZE); - CalculateMinerTxHash(hashes.data()); + //CalculateMinerTxHash(hashes.data()); for (uint64_t i = 1; i <= num_hashes; ++i) { uint8_t h[HASH_SIZE]; @@ -116,14 +122,14 @@ bool CBlockTemplate::Init(const String& blockTemplate) memcpy(hashes.data() + i * HASH_SIZE, h, HASH_SIZE); } - CalculateMerkleTreeHash(hashes.data(), num_hashes + 1, root_hash); - CalculateHashingBlob(); + //CalculateMerkleTreeHash(hashes.data(), num_hashes + 1, root_hash); + //CalculateHashingBlob(); return true; } -void CBlockTemplate::CalculateMinerTxHash(uint8_t* hash) +void BlockTemplate::CalculateMinerTxHash(uint8_t* hash) { uint8_t hashes[HASH_SIZE * 3]; @@ -147,7 +153,7 @@ void CBlockTemplate::CalculateMinerTxHash(uint8_t* hash) -void CBlockTemplate::CalculateMerkleTreeHash(const uint8_t* hashes, size_t count, uint8_t* root_hash) +void BlockTemplate::CalculateMerkleTreeHash(const uint8_t* hashes, size_t count, uint8_t* root_hash) { if (count == 1) { memcpy(root_hash, hashes, HASH_SIZE); @@ -180,7 +186,7 @@ void CBlockTemplate::CalculateMerkleTreeHash(const uint8_t* hashes, size_t count } -void CBlockTemplate::CalculateHashingBlob() +void BlockTemplate::CalculateHashingBlob() { hashingBlob.clear(); hashingBlob.reserve(miner_tx_prefix_begin_index + HASH_SIZE + 3); @@ -194,9 +200,6 @@ void CBlockTemplate::CalculateHashingBlob() k >>= 7; } hashingBlob.emplace_back(static_cast(k)); - - for (int i = 0; i < hashingBlob.size(); ++i) - printf("%02x", hashingBlob[i]); } diff --git a/src/base/tools/cryptonote/BlockTemplate.h b/src/base/tools/cryptonote/BlockTemplate.h index bf87b5d6..be896b49 100644 --- a/src/base/tools/cryptonote/BlockTemplate.h +++ b/src/base/tools/cryptonote/BlockTemplate.h @@ -22,6 +22,7 @@ #define XMRIG_BLOCKTEMPLATE_H +#include "base/crypto/Coin.h" #include "base/tools/Buffer.h" #include "base/tools/String.h" @@ -29,11 +30,12 @@ namespace xmrig { -struct CBlockTemplate +struct BlockTemplate { enum { HASH_SIZE = 32, KEY_SIZE = 32, + SIGNATURE_SIZE = 64, NONCE_SIZE = 4, }; @@ -50,6 +52,9 @@ struct CBlockTemplate uint8_t prev_id[HASH_SIZE]; uint8_t nonce[NONCE_SIZE]; + bool has_miner_signature; + uint8_t miner_signature[SIGNATURE_SIZE]; + // Miner tx uint64_t tx_version; uint64_t unlock_time; @@ -72,7 +77,7 @@ struct CBlockTemplate Buffer hashingBlob; - bool Init(const String& blockTemplate); + bool Init(const String& blockTemplate, Coin coin); private: void CalculateMinerTxHash(uint8_t* hash); diff --git a/src/core/config/Config_platform.h b/src/core/config/Config_platform.h index f92a3158..2867a8b7 100644 --- a/src/core/config/Config_platform.h +++ b/src/core/config/Config_platform.h @@ -96,6 +96,7 @@ static const option options[] = { { "pause-on-active", 1, nullptr, IConfig::PauseOnActiveKey }, { "dns-ipv6", 0, nullptr, IConfig::DnsIPv6Key }, { "dns-ttl", 1, nullptr, IConfig::DnsTtlKey }, + { "spend-secret-key", 1, nullptr, IConfig::SpendSecretKey }, # ifdef XMRIG_FEATURE_BENCHMARK { "stress", 0, nullptr, IConfig::StressKey }, { "bench", 1, nullptr, IConfig::BenchKey }, diff --git a/src/net/JobResult.h b/src/net/JobResult.h index 7c818e2c..22fbb311 100644 --- a/src/net/JobResult.h +++ b/src/net/JobResult.h @@ -43,7 +43,7 @@ class JobResult public: JobResult() = delete; - inline JobResult(const Job &job, uint64_t nonce, const uint8_t *result, const uint8_t* header_hash = nullptr, const uint8_t *mix_hash = nullptr) : + inline JobResult(const Job &job, uint64_t nonce, const uint8_t *result, const uint8_t* header_hash = nullptr, const uint8_t *mix_hash = nullptr, const uint8_t* miner_signature = nullptr) : algorithm(job.algorithm()), clientId(job.clientId()), jobId(job.id()), @@ -61,6 +61,10 @@ public: if (mix_hash) { memcpy(m_mixHash, mix_hash, sizeof(m_mixHash)); } + + if (miner_signature) { + memcpy(m_minerSignature, miner_signature, sizeof(m_minerSignature)); + } } inline JobResult(const Job &job) : @@ -80,6 +84,8 @@ public: inline const uint8_t *headerHash() const { return m_headerHash; } inline const uint8_t *mixHash() const { return m_mixHash; } + inline const uint8_t *minerSignature() const { return m_minerSignature; } + const Algorithm algorithm; const String clientId; const String jobId; @@ -92,6 +98,8 @@ private: uint8_t m_result[32] = { 0 }; uint8_t m_headerHash[32] = { 0 }; uint8_t m_mixHash[32] = { 0 }; + + uint8_t m_minerSignature[64] = { 0 }; }; diff --git a/src/net/JobResults.cpp b/src/net/JobResults.cpp index 4040cd9a..bcf1abd1 100644 --- a/src/net/JobResults.cpp +++ b/src/net/JobResults.cpp @@ -341,6 +341,12 @@ void xmrig::JobResults::submit(const Job &job, uint32_t nonce, const uint8_t *re } +void xmrig::JobResults::submit(const Job& job, uint32_t nonce, const uint8_t* result, const uint8_t* miner_signature) +{ + submit(JobResult(job, nonce, result, nullptr, nullptr, miner_signature)); +} + + void xmrig::JobResults::submit(const JobResult &result) { assert(handler != nullptr); diff --git a/src/net/JobResults.h b/src/net/JobResults.h index 5ca243d7..33a8a826 100644 --- a/src/net/JobResults.h +++ b/src/net/JobResults.h @@ -46,6 +46,7 @@ public: static void setListener(IJobResultListener *listener, bool hwAES); static void stop(); static void submit(const Job &job, uint32_t nonce, const uint8_t *result); + static void submit(const Job& job, uint32_t nonce, const uint8_t* result, const uint8_t* miner_signature); static void submit(const JobResult &result); # if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA) diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index 28a1b1cd..a8ecf851 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -77,9 +77,9 @@ xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener # endif # ifdef XMRIG_FEATURE_TLS - m_pools.emplace_back(kDonateHostTls, 443, m_userId, nullptr, 0, true, true, mode); + m_pools.emplace_back(kDonateHostTls, 443, m_userId, nullptr, nullptr, 0, true, true, mode); # endif - m_pools.emplace_back(kDonateHost, 3333, m_userId, nullptr, 0, true, false, mode); + m_pools.emplace_back(kDonateHost, 3333, m_userId, nullptr, nullptr, 0, true, false, mode); if (m_pools.size() > 1) { m_strategy = new FailoverStrategy(m_pools, 10, 2, this, true); @@ -259,7 +259,7 @@ xmrig::IClient *xmrig::DonateStrategy::createProxy() const IClient *client = strategy->client(); m_tls = client->hasExtension(IClient::EXT_TLS); - Pool pool(client->pool().proxy().isValid() ? client->pool().host() : client->ip(), client->pool().port(), m_userId, client->pool().password(), 0, true, client->isTLS(), Pool::MODE_POOL); + Pool pool(client->pool().proxy().isValid() ? client->pool().host() : client->ip(), client->pool().port(), m_userId, client->pool().password(), nullptr, 0, true, client->isTLS(), Pool::MODE_POOL); pool.setAlgo(client->pool().algorithm()); pool.setProxy(client->pool().proxy());