feat: Add stratum integration and mining support for new algorithms

- 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 <noreply@anthropic.com>
This commit is contained in:
snider 2025-12-30 20:56:19 +00:00
parent 9cf0db802a
commit b1aced8341
9 changed files with 151 additions and 22 deletions

View file

@ -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<N>::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<N>::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;

View file

@ -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;

View file

@ -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 ") },
};

View file

@ -41,6 +41,10 @@ public:
ZEPHYR,
TOWNFORGE,
YADA,
ETHEREUM_CLASSIC,
ETHEREUM,
ZANO,
DECRED,
MAX
};

View file

@ -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;
}

View file

@ -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;
}

View file

@ -76,7 +76,10 @@ public:
inline const String &poolWallet() const { return m_poolWallet; }
inline const uint32_t *nonce() const { return reinterpret_cast<const uint32_t*>(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<uint32_t*>(m_blob + nonceOffset()); }
inline uint32_t backend() const { return m_backend; }

View file

@ -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);
}

View file

@ -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
}