From 37d4ae0d1b010f71393d229cd669d0fa363bcf5d Mon Sep 17 00:00:00 2001 From: Capri Date: Thu, 17 Sep 2026 18:31:43 +0000 Subject: [PATCH] Add algorithm-aware mining difficulty --- src/rpc/blockchain.cpp | 37 ++++++++++++++++++++++++++++++++++- src/rpc/blockchain.h | 15 ++++++++++++++ src/rpc/mining.cpp | 10 ++++++++-- src/test/blockchain_tests.cpp | 33 +++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 92e9793..d597bcc 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -137,11 +137,46 @@ double GetDifficulty(const CBlockIndex* blockindex) return dDiff; } +double GetAlgoDifficulty( + const CBlockIndex* blockindex, + const Consensus::Params& consensusParams, + int algo) +{ + assert(blockindex != nullptr); + + if (algo == ALGO_SHA256D) { + return GetDifficulty(blockindex); + } + + if (algo != ALGO_RANDOMX) { + return 0.0; + } + + bool negative; + bool overflow; + + arith_uint256 target; + target.SetCompact(blockindex->nBits, &negative, &overflow); + + if (negative || overflow || target == 0) { + return 0.0; + } + + const arith_uint256 reference = + UintToArith256(consensusParams.randomXInitialTarget); + + if (reference == 0) { + return 0.0; + } + + return reference.getdouble() / target.getdouble(); +} + static double GetNextDifficulty(const CBlockIndex* tip, const Consensus::Params& consensusParams, int algo) { CBlockIndex next; next.nBits = GetNextWorkRequired(tip, nullptr, consensusParams, algo); - return GetDifficulty(&next); + return GetAlgoDifficulty(&next, consensusParams, algo); } static int ComputeNextBlockAndDepth(const CBlockIndex* tip, const CBlockIndex* blockindex, const CBlockIndex*& next) diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h index 078b3b5..9425c30 100644 --- a/src/rpc/blockchain.h +++ b/src/rpc/blockchain.h @@ -26,6 +26,10 @@ class ChainstateManager; class UniValue; struct NodeContext; +namespace Consensus { +struct Params; +} + static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5; /** @@ -36,6 +40,17 @@ static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5; */ double GetDifficulty(const CBlockIndex* blockindex); +/** + * Get difficulty for a specific mining algorithm. + * + * SHA256D preserves the legacy GetDifficulty() scale. + * RandomX uses randomXInitialTarget as difficulty 1.0. + */ +double GetAlgoDifficulty( + const CBlockIndex* blockindex, + const Consensus::Params& consensusParams, + int algo); + /** Callback for when block tip changed. */ void RPCNotifyBlockChange(const CBlockIndex*); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 27951ad..86c89d3 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -678,9 +678,15 @@ static RPCHelpMan getmininginfo() GetNextWorkRequired(tip, nullptr, consensusParams, ALGO_RANDOMX); const double sha_difficulty = - GetDifficulty(&sha_next); + GetAlgoDifficulty( + &sha_next, + consensusParams, + ALGO_SHA256D); const double randomx_difficulty = - GetDifficulty(&randomx_next); + GetAlgoDifficulty( + &randomx_next, + consensusParams, + ALGO_RANDOMX); difficulties.pushKV( GetMiningAlgoName(ALGO_SHA256D), diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp index 30999e2..a74c011 100644 --- a/src/test/blockchain_tests.cpp +++ b/src/test/blockchain_tests.cpp @@ -7,6 +7,8 @@ #include #include +#include +#include #include #include #include @@ -74,4 +76,35 @@ BOOST_AUTO_TEST_CASE(get_difficulty_for_very_high_target) TestDifficulty(0x12345678, 5913134931067755359633408.0); } +BOOST_AUTO_TEST_CASE(get_algo_difficulty) +{ + const auto chainParams = + CreateChainParams(*m_node.args, CBaseChainParams::MAIN); + const auto& consensus = chainParams->GetConsensus(); + + CBlockIndex sha; + sha.nBits = UintToArith256(consensus.powLimit).GetCompact(); + + BOOST_CHECK_EQUAL( + GetAlgoDifficulty(&sha, consensus, ALGO_SHA256D), + GetDifficulty(&sha)); + + CBlockIndex randomx; + randomx.nBits = + UintToArith256(consensus.randomXInitialTarget).GetCompact(); + + RejectDifficultyMismatch( + GetAlgoDifficulty(&randomx, consensus, ALGO_RANDOMX), + 1.0); + + arith_uint256 harderRandomXTarget = + UintToArith256(consensus.randomXInitialTarget); + harderRandomXTarget /= 2; + randomx.nBits = harderRandomXTarget.GetCompact(); + + RejectDifficultyMismatch( + GetAlgoDifficulty(&randomx, consensus, ALGO_RANDOMX), + 2.0); +} + BOOST_AUTO_TEST_SUITE_END()