From b1aced8341ddc096312f7e498c89bbfaaf3837b0 Mon Sep 17 00:00:00 2001 From: snider Date: Tue, 30 Dec 2025 20:56:19 +0000 Subject: [PATCH] feat: Add stratum integration and mining support for new algorithms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Stratum protocol integration for ETChash, ProgPowZ, Blake3DCR - EthStratumClient selection for DAG-based algorithms - Nonce offset handling for all new algorithm families - AutoClient support for new algorithm detection - Coin definitions for ETC, ETH, ZANO, DCR Worker integration: - CPU worker support for Blake3DCR mining - GPU worker stubs for ETChash, ProgPowZ, Blake3 - Proper algorithm family handling in CpuWorker/OclWorker Go CLI integration: - Updated xmrig_start.go with coin field support - Improved pool configuration for new algorithms 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- miner/core/src/backend/cpu/CpuWorker.cpp | 48 +++++++++++++++++++ miner/core/src/backend/opencl/OclWorker.cpp | 24 ++++++++++ miner/core/src/base/crypto/Coin.cpp | 4 ++ miner/core/src/base/crypto/Coin.h | 4 ++ .../core/src/base/net/stratum/AutoClient.cpp | 10 +++- miner/core/src/base/net/stratum/Job.cpp | 15 ++++++ miner/core/src/base/net/stratum/Job.h | 5 +- miner/core/src/base/net/stratum/Pool.cpp | 17 +++++-- pkg/mining/xmrig_start.go | 46 +++++++++++------- 9 files changed, 151 insertions(+), 22 deletions(-) diff --git a/miner/core/src/backend/cpu/CpuWorker.cpp b/miner/core/src/backend/cpu/CpuWorker.cpp index cba7e88..efc00ec 100644 --- a/miner/core/src/backend/cpu/CpuWorker.cpp +++ b/miner/core/src/backend/cpu/CpuWorker.cpp @@ -44,6 +44,10 @@ # include "crypto/randomx/randomx.h" #endif +#ifdef XMRIG_ALGO_BLAKE3DCR +# include "crypto/blake3dcr/Blake3DCR.h" +#endif + #ifdef XMRIG_FEATURE_BENCHMARK # include "backend/common/benchmark/BenchState.h" @@ -225,6 +229,27 @@ bool xmrig::CpuWorker::selfTest() } # endif +# ifdef XMRIG_ALGO_BLAKE3DCR + if (m_algorithm.family() == Algorithm::BLAKE3) { + // Blake3 is a simple hash, supports any N value + return N >= 1; + } +# endif + +# ifdef XMRIG_ALGO_ETCHASH + if (m_algorithm.family() == Algorithm::ETCHASH) { + // ETChash/Ethash are GPU-only algorithms + return false; + } +# endif + +# ifdef XMRIG_ALGO_PROGPOWZ + if (m_algorithm.family() == Algorithm::PROGPOWZ) { + // ProgPowZ is a GPU-only algorithm + return false; + } +# endif + return false; } @@ -325,6 +350,29 @@ void xmrig::CpuWorker::start() break; # endif +# ifdef XMRIG_ALGO_BLAKE3DCR + case Algorithm::BLAKE3: + // Blake3 hash for each parallel hash slot + for (size_t i = 0; i < N; ++i) { + Blake3DCR::hash(m_job.blob() + (i * job.size()), job.size(), m_hash + (i * 32)); + } + break; +# endif + +# ifdef XMRIG_ALGO_ETCHASH + case Algorithm::ETCHASH: + // ETChash/Ethash CPU mining not supported (GPU-only algorithm) + valid = false; + break; +# endif + +# ifdef XMRIG_ALGO_PROGPOWZ + case Algorithm::PROGPOWZ: + // ProgPowZ CPU mining not supported (GPU-only algorithm) + valid = false; + break; +# endif + default: fn(job.algorithm())(m_job.blob(), job.size(), m_hash, m_ctx, job.height()); break; diff --git a/miner/core/src/backend/opencl/OclWorker.cpp b/miner/core/src/backend/opencl/OclWorker.cpp index dcac60b..9b5be37 100644 --- a/miner/core/src/backend/opencl/OclWorker.cpp +++ b/miner/core/src/backend/opencl/OclWorker.cpp @@ -92,6 +92,30 @@ xmrig::OclWorker::OclWorker(size_t id, const OclLaunchData &data) : # endif break; +# ifdef XMRIG_ALGO_ETCHASH + case Algorithm::ETCHASH: + // ETChash/Ethash GPU support - uses ethash DAG similar to KawPow + // TODO: Implement OclEtchashRunner with proper ethash kernel + m_runner = nullptr; + break; +# endif + +# ifdef XMRIG_ALGO_PROGPOWZ + case Algorithm::PROGPOWZ: + // ProgPowZ GPU support - ProgPow variant used by Zano + // TODO: Implement OclProgPowZRunner with ProgPowZ kernel + m_runner = nullptr; + break; +# endif + +# ifdef XMRIG_ALGO_BLAKE3DCR + case Algorithm::BLAKE3: + // Blake3 GPU support - fast cryptographic hash for Decred + // TODO: Implement OclBlake3Runner + m_runner = nullptr; + break; +# endif + default: m_runner = new OclCnRunner(id, data); break; diff --git a/miner/core/src/base/crypto/Coin.cpp b/miner/core/src/base/crypto/Coin.cpp index 85cc605..cbec279 100644 --- a/miner/core/src/base/crypto/Coin.cpp +++ b/miner/core/src/base/crypto/Coin.cpp @@ -55,6 +55,10 @@ static const CoinInfo coinInfo[] = { { Algorithm::RX_0, "ZEPH", "Zephyr", 120, 1000000000000, BLUE_BG_BOLD( WHITE_BOLD_S " zephyr ") }, { Algorithm::RX_0, "Townforge","Townforge", 30, 100000000, MAGENTA_BG_BOLD(WHITE_BOLD_S " townforge ") }, { Algorithm::RX_YADA, "YDA", "YadaCoin", 120, 100000000, BLUE_BG_BOLD( WHITE_BOLD_S " yada ") }, + { Algorithm::ETCHASH_ETC, "ETC", "Ethereum Classic", 13, 1000000000000000000, GREEN_BG_BOLD( WHITE_BOLD_S " etc ") }, + { Algorithm::ETHASH_ETH, "ETH", "Ethereum", 12, 1000000000000000000, BLUE_BG_BOLD( WHITE_BOLD_S " eth ") }, + { Algorithm::PROGPOWZ_ZANO, "ZANO", "Zano", 60, 1000000000000, CYAN_BG_BOLD( WHITE_BOLD_S " zano ") }, + { Algorithm::BLAKE3_DCR, "DCR", "Decred", 300, 100000000, GREEN_BG_BOLD( WHITE_BOLD_S " decred ") }, }; diff --git a/miner/core/src/base/crypto/Coin.h b/miner/core/src/base/crypto/Coin.h index c3c97fd..7e3ef49 100644 --- a/miner/core/src/base/crypto/Coin.h +++ b/miner/core/src/base/crypto/Coin.h @@ -41,6 +41,10 @@ public: ZEPHYR, TOWNFORGE, YADA, + ETHEREUM_CLASSIC, + ETHEREUM, + ZANO, + DECRED, MAX }; diff --git a/miner/core/src/base/net/stratum/AutoClient.cpp b/miner/core/src/base/net/stratum/AutoClient.cpp index 675be86..425478b 100644 --- a/miner/core/src/base/net/stratum/AutoClient.cpp +++ b/miner/core/src/base/net/stratum/AutoClient.cpp @@ -50,7 +50,15 @@ bool xmrig::AutoClient::parseLogin(const rapidjson::Value &result, int *code) } const Algorithm algo(Json::getString(result, "algo")); - if (algo.family() != Algorithm::KAWPOW && algo.family() != Algorithm::GHOSTRIDER) { + const auto family = algo.family(); + if (family != Algorithm::KAWPOW && family != Algorithm::GHOSTRIDER +# ifdef XMRIG_ALGO_ETCHASH + && family != Algorithm::ETCHASH +# endif +# ifdef XMRIG_ALGO_PROGPOWZ + && family != Algorithm::PROGPOWZ +# endif + ) { *code = 6; return false; } diff --git a/miner/core/src/base/net/stratum/Job.cpp b/miner/core/src/base/net/stratum/Job.cpp index 1a7cfbf..d730357 100644 --- a/miner/core/src/base/net/stratum/Job.cpp +++ b/miner/core/src/base/net/stratum/Job.cpp @@ -161,6 +161,21 @@ size_t xmrig::Job::nonceOffset() const case Algorithm::GHOSTRIDER: return 76; +# ifdef XMRIG_ALGO_ETCHASH + case Algorithm::ETCHASH: + return 32; // ETChash/Ethash uses 32-byte header hash + 8-byte nonce +# endif + +# ifdef XMRIG_ALGO_PROGPOWZ + case Algorithm::PROGPOWZ: + return 32; // ProgPowZ follows same pattern as KawPow/Ethash +# endif + +# ifdef XMRIG_ALGO_BLAKE3DCR + case Algorithm::BLAKE3: + return 140; // Decred block header nonce offset +# endif + default: break; } diff --git a/miner/core/src/base/net/stratum/Job.h b/miner/core/src/base/net/stratum/Job.h index 8e28c1b..cd61626 100644 --- a/miner/core/src/base/net/stratum/Job.h +++ b/miner/core/src/base/net/stratum/Job.h @@ -76,7 +76,10 @@ public: inline const String &poolWallet() const { return m_poolWallet; } inline const uint32_t *nonce() const { return reinterpret_cast(m_blob + nonceOffset()); } inline const uint8_t *blob() const { return m_blob; } - inline size_t nonceSize() const { return (algorithm().family() == Algorithm::KAWPOW) ? 8 : 4; } + inline size_t nonceSize() const { + const auto family = algorithm().family(); + return (family == Algorithm::KAWPOW || family == Algorithm::ETCHASH || family == Algorithm::PROGPOWZ) ? 8 : 4; + } inline size_t size() const { return m_size; } inline uint32_t *nonce() { return reinterpret_cast(m_blob + nonceOffset()); } inline uint32_t backend() const { return m_backend; } diff --git a/miner/core/src/base/net/stratum/Pool.cpp b/miner/core/src/base/net/stratum/Pool.cpp index 8b4a6e0..daf67ae 100644 --- a/miner/core/src/base/net/stratum/Pool.cpp +++ b/miner/core/src/base/net/stratum/Pool.cpp @@ -31,7 +31,7 @@ #include "base/kernel/Platform.h" #include "base/net/stratum/Client.h" -#if defined XMRIG_ALGO_KAWPOW || defined XMRIG_ALGO_GHOSTRIDER +#if defined XMRIG_ALGO_KAWPOW || defined XMRIG_ALGO_GHOSTRIDER || defined XMRIG_ALGO_ETCHASH || defined XMRIG_ALGO_PROGPOWZ # include "base/net/stratum/AutoClient.h" # include "base/net/stratum/EthStratumClient.h" #endif @@ -226,9 +226,18 @@ xmrig::IClient *xmrig::Pool::createClient(int id, IClientListener *listener) con IClient *client = nullptr; if (m_mode == MODE_POOL) { -# if defined XMRIG_ALGO_KAWPOW || defined XMRIG_ALGO_GHOSTRIDER +# if defined XMRIG_ALGO_KAWPOW || defined XMRIG_ALGO_GHOSTRIDER || defined XMRIG_ALGO_ETCHASH || defined XMRIG_ALGO_PROGPOWZ const uint32_t f = m_algorithm.family(); - if ((f == Algorithm::KAWPOW) || (f == Algorithm::GHOSTRIDER) || (m_coin == Coin::RAVEN)) { + const bool isEthStratum = (f == Algorithm::KAWPOW) || (f == Algorithm::GHOSTRIDER) || (f == Algorithm::ETCHASH) || (f == Algorithm::PROGPOWZ) + || (m_coin == Coin::RAVEN) +# ifdef XMRIG_ALGO_ETCHASH + || (m_coin == Coin::ETHEREUM_CLASSIC) || (m_coin == Coin::ETHEREUM) +# endif +# ifdef XMRIG_ALGO_PROGPOWZ + || (m_coin == Coin::ZANO) +# endif + ; + if (isEthStratum) { client = new EthStratumClient(id, Platform::userAgent(), listener); } else @@ -245,7 +254,7 @@ xmrig::IClient *xmrig::Pool::createClient(int id, IClientListener *listener) con client = new SelfSelectClient(id, Platform::userAgent(), listener, m_submitToOrigin); } # endif -# if defined XMRIG_ALGO_KAWPOW || defined XMRIG_ALGO_GHOSTRIDER +# if defined XMRIG_ALGO_KAWPOW || defined XMRIG_ALGO_GHOSTRIDER || defined XMRIG_ALGO_ETCHASH || defined XMRIG_ALGO_PROGPOWZ else if (m_mode == MODE_AUTO_ETH) { client = new AutoClient(id, Platform::userAgent(), listener); } diff --git a/pkg/mining/xmrig_start.go b/pkg/mining/xmrig_start.go index 3380ef1..9effa6e 100644 --- a/pkg/mining/xmrig_start.go +++ b/pkg/mining/xmrig_start.go @@ -167,16 +167,20 @@ func (m *XMRigMiner) createConfig(config *Config) error { } // Build pools array - CPU pool first - pools := []map[string]interface{}{ - { - "url": config.Pool, - "user": config.Wallet, - "pass": "x", - "keepalive": true, - "tls": config.TLS, - "algo": config.Algo, - }, + cpuPool := map[string]interface{}{ + "url": config.Pool, + "user": config.Wallet, + "pass": "x", + "keepalive": true, + "tls": config.TLS, } + // Add algo or coin (coin takes precedence for algorithm auto-detection) + if config.Coin != "" { + cpuPool["coin"] = config.Coin + } else if config.Algo != "" { + cpuPool["algo"] = config.Algo + } + pools := []map[string]interface{}{cpuPool} // Add separate GPU pool if configured if config.GPUEnabled && config.GPUPool != "" { @@ -188,20 +192,27 @@ func (m *XMRigMiner) createConfig(config *Config) error { if gpuPass == "" { gpuPass = "x" } - pools = append(pools, map[string]interface{}{ + gpuPool := map[string]interface{}{ "url": config.GPUPool, "user": gpuWallet, "pass": gpuPass, "keepalive": true, - "algo": config.GPUAlgo, - }) + } + // Add GPU algo (typically etchash, ethash, kawpow, progpowz for GPU mining) + if config.GPUAlgo != "" { + gpuPool["algo"] = config.GPUAlgo + } + pools = append(pools, gpuPool) } // Build OpenCL (AMD/Intel GPU) config + // GPU mining requires explicit device selection - no auto-picking openclConfig := map[string]interface{}{ - "enabled": config.GPUEnabled && config.OpenCL, + "enabled": config.GPUEnabled && config.OpenCL && config.Devices != "", } - if config.GPUEnabled && config.OpenCL { + if config.GPUEnabled && config.OpenCL && config.Devices != "" { + // User must explicitly specify devices (e.g., "0" or "0,1") + openclConfig["devices"] = config.Devices if config.GPUIntensity > 0 { openclConfig["intensity"] = config.GPUIntensity } @@ -211,10 +222,13 @@ func (m *XMRigMiner) createConfig(config *Config) error { } // Build CUDA (NVIDIA GPU) config + // GPU mining requires explicit device selection - no auto-picking cudaConfig := map[string]interface{}{ - "enabled": config.GPUEnabled && config.CUDA, + "enabled": config.GPUEnabled && config.CUDA && config.Devices != "", } - if config.GPUEnabled && config.CUDA { + if config.GPUEnabled && config.CUDA && config.Devices != "" { + // User must explicitly specify devices (e.g., "0" or "0,1") + cudaConfig["devices"] = config.Devices if config.GPUIntensity > 0 { cudaConfig["intensity"] = config.GPUIntensity }