Data + service layer for supporting multiple mining pools: - pool_registry: KnownPool table (pool.dragonx.is + pool.dragonx.cc) carrying each pool's stratum host, xmrig algo, and stats-API schema; pure helpers findKnownPoolByUrl / resolvePoolAlgo / parsePoolHashrate / chooseWeightedPool (weighted-random by hashrate with incumbent stickiness). - pool_stats_service: background, schema-aware hashrate fetcher (libcurl, TLS, browser UA for Cloudflare) modelled on XmrigUpdater. - settings: pool_select_mode (manual | auto_balance), string-serialized. - i18n strings + unit tests (both stats schemas, algo resolution, weighted pick). Note: pool.dragonx.cc's stratum host is us.dragonx.cc:3333 — the .cc domain is only the Cloudflare-proxied web/API host and does not accept stratum on :3333. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
82 lines
3.7 KiB
C++
82 lines
3.7 KiB
C++
// DragonX Wallet - ImGui Edition
|
|
// Copyright 2024-2026 The Hush Developers
|
|
// Released under the GPLv3
|
|
//
|
|
// PoolRegistry — the small table of official DragonX mining pools plus the pure
|
|
// (no-I/O) helpers used to compare their hashrate and pick one for auto-balance.
|
|
//
|
|
// A pool is more than a URL: the two official pools speak DIFFERENT stats APIs
|
|
// (pool.dragonx.is = a custom /api/stats; pool.dragonx.cc = Miningcore /api/pools)
|
|
// and mine with DIFFERENT algo strings (rx/hush vs rx/dragonx), so each entry
|
|
// carries how to read its hashrate and which algo xmrig must be told to use.
|
|
//
|
|
// Everything here is pure and unit-tested (see tests/test_phase4.cpp); the live
|
|
// HTTP fetch lives in pool_stats_service.{h,cpp}.
|
|
|
|
#pragma once
|
|
|
|
#include <random>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace dragonx {
|
|
namespace util {
|
|
|
|
// How to read a pool's total hashrate from its public stats JSON.
|
|
enum class PoolStatsSchema {
|
|
DragonXIs, // GET /api/stats -> pools.<name>.hashrate (custom)
|
|
Miningcore, // GET /api/pools -> pools[id==poolId].poolStats.poolHashrate (Miningcore)
|
|
};
|
|
|
|
struct KnownPool {
|
|
std::string id; // stable internal id, e.g. "dragonx-cc-pplns"
|
|
std::string label; // human label for the UI (host, sans port)
|
|
std::string stratum; // host:port the miner connects to
|
|
std::string algo; // xmrig algo string for THIS pool
|
|
std::string statsUrl; // absolute https URL of the stats endpoint
|
|
PoolStatsSchema schema = PoolStatsSchema::DragonXIs;
|
|
std::string miningcorePoolId; // Miningcore pool id (empty for DragonXIs)
|
|
double feePercent = 0.0; // pool fee, for display only
|
|
bool official = true;
|
|
};
|
|
|
|
// A pool's live total hashrate sample (H/s). ok=false when the fetch/parse failed.
|
|
struct PoolHashrate {
|
|
std::string id;
|
|
double hashrateHs = 0.0;
|
|
bool ok = false;
|
|
};
|
|
|
|
// The built-in official pools (PPLNS only — never a SOLO pool, whose hashrate is
|
|
// meaningless to balance against). Stable order.
|
|
const std::vector<KnownPool>& knownPools();
|
|
|
|
// The known pool whose stratum matches `url` (host, and port when both specify one),
|
|
// or nullptr. `url` may be a bare host, host:port, or carry a scheme/userinfo/path.
|
|
const KnownPool* findKnownPoolByUrl(const std::string& url);
|
|
|
|
// The algo xmrig must use for `url`: the matching known pool's algo, else `fallback`.
|
|
std::string resolvePoolAlgo(const std::string& url, const std::string& fallback);
|
|
|
|
// Parse a pool's total hashrate (H/s) out of its stats JSON per `schema`.
|
|
// `miningcorePoolId` selects the pool entry for the Miningcore schema (ignored
|
|
// otherwise). Sets ok=false and returns 0 on any parse failure / missing field.
|
|
double parsePoolHashrate(PoolStatsSchema schema, const std::string& json,
|
|
const std::string& miningcorePoolId, bool& ok);
|
|
|
|
// Weighted-random pick among the usable (ok==true) pools: probability is inversely
|
|
// proportional to hashrate (smaller pools favored), so miners spread out instead of
|
|
// all stampeding to the single lowest pool. The current pool (`currentId`, may be
|
|
// empty) gets a stickiness multiplier so re-balancing rarely churns the miner.
|
|
// Returns the chosen pool id; returns `currentId` (or the sole usable id) when fewer
|
|
// than two pools are usable.
|
|
std::string chooseWeightedPool(const std::vector<PoolHashrate>& pools,
|
|
const std::string& currentId,
|
|
std::mt19937& rng);
|
|
|
|
// Stickiness applied to the incumbent pool's weight in chooseWeightedPool.
|
|
inline constexpr double kIncumbentStayBias = 2.0;
|
|
|
|
} // namespace util
|
|
} // namespace dragonx
|