diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index e9046fa71d0..5e3d1120e32 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -428,6 +428,13 @@ static RPCHelpMan getmininginfo() {RPCResult::Type::NUM, "pooledtx", "The size of the mempool"}, {RPCResult::Type::STR, "chain", "current network name (" LIST_CHAIN_NAMES ")"}, {RPCResult::Type::STR_HEX, "signet_challenge", /*optional=*/true, "The block challenge (aka. block script), in hexadecimal (only present if the current network is a signet)"}, + {RPCResult::Type::OBJ, "next", "The next block", + { + {RPCResult::Type::NUM, "height", "The next height"}, + {RPCResult::Type::STR_HEX, "bits", "The next target nBits"}, + {RPCResult::Type::NUM, "difficulty", "The next difficulty"}, + {RPCResult::Type::STR_HEX, "target", "The next target"} + }}, (IsDeprecatedRPCEnabled("warnings") ? RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} : RPCResult{RPCResult::Type::ARR, "warnings", "any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)", @@ -460,9 +467,20 @@ static RPCHelpMan getmininginfo() obj.pushKV("networkhashps", getnetworkhashps().HandleRequest(request)); obj.pushKV("pooledtx", (uint64_t)mempool.size()); obj.pushKV("chain", chainman.GetParams().GetChainTypeString()); + + UniValue next(UniValue::VOBJ); + CBlockIndex next_index; + NextEmptyBlockIndex(tip, chainman.GetConsensus(), next_index); + + next.pushKV("height", next_index.nHeight); + next.pushKV("bits", strprintf("%08x", next_index.nBits)); + next.pushKV("difficulty", GetDifficulty(next_index)); + next.pushKV("target", GetTarget(next_index, chainman.GetConsensus().powLimit).GetHex()); + obj.pushKV("next", next); + if (chainman.GetParams().GetChainType() == ChainType::SIGNET) { const std::vector& signet_challenge = - chainman.GetParams().GetConsensus().signet_challenge; + chainman.GetConsensus().signet_challenge; obj.pushKV("signet_challenge", HexStr(signet_challenge)); } obj.pushKV("warnings", node::GetWarningsForRpc(*CHECK_NONFATAL(node.warnings), IsDeprecatedRPCEnabled("warnings"))); diff --git a/src/rpc/server_util.cpp b/src/rpc/server_util.cpp index 0387cbb8e25..0edd7527a95 100644 --- a/src/rpc/server_util.cpp +++ b/src/rpc/server_util.cpp @@ -4,10 +4,13 @@ #include +#include #include #include #include +#include #include +#include #include #include #include @@ -17,6 +20,7 @@ #include using node::NodeContext; +using node::UpdateTime; NodeContext& EnsureAnyNodeContext(const std::any& context) { @@ -129,3 +133,18 @@ AddrMan& EnsureAnyAddrman(const std::any& context) { return EnsureAddrman(EnsureAnyNodeContext(context)); } + +void NextEmptyBlockIndex(CBlockIndex& tip, const Consensus::Params& consensusParams, CBlockIndex& next_index) +{ + CBlockHeader next_header{}; + next_header.hashPrevBlock = tip.GetBlockHash(); + UpdateTime(&next_header, consensusParams, &tip); + next_header.nBits = GetNextWorkRequired(&tip, &next_header, consensusParams); + next_header.nNonce = 0; + + next_index.pprev = &tip; + next_index.nTime = next_header.nTime; + next_index.nBits = next_header.nBits; + next_index.nNonce = next_header.nNonce; + next_index.nHeight = tip.nHeight + 1; +} diff --git a/src/rpc/server_util.h b/src/rpc/server_util.h index 1e6fb7e6a66..6fb5e1c9b35 100644 --- a/src/rpc/server_util.h +++ b/src/rpc/server_util.h @@ -7,8 +7,11 @@ #include +#include + class AddrMan; class ArgsManager; +class CBlockIndex; class CBlockPolicyEstimator; class CConnman; class CTxMemPool; @@ -39,4 +42,7 @@ PeerManager& EnsurePeerman(const node::NodeContext& node); AddrMan& EnsureAddrman(const node::NodeContext& node); AddrMan& EnsureAnyAddrman(const std::any& context); +/** Return an empty block index on top of the tip, with height, time and nBits set */ +void NextEmptyBlockIndex(CBlockIndex& tip, const Consensus::Params& consensusParams, CBlockIndex& next_index); + #endif // BITCOIN_RPC_SERVER_UTIL_H diff --git a/test/functional/mining_basic.py b/test/functional/mining_basic.py index 86d9802e729..979eda7d042 100755 --- a/test/functional/mining_basic.py +++ b/test/functional/mining_basic.py @@ -213,6 +213,12 @@ class MiningTest(BitcoinTestFramework): assert_equal(mining_info['bits'], nbits_str(REGTEST_N_BITS)) assert_equal(mining_info['target'], target_str(REGTEST_TARGET)) assert_equal(mining_info['difficulty'], Decimal('4.656542373906925E-10')) + assert_equal(mining_info['next'], { + 'height': 201, + 'target': target_str(REGTEST_TARGET), + 'bits': nbits_str(REGTEST_N_BITS), + 'difficulty': Decimal('4.656542373906925E-10') + }) assert_equal(mining_info['networkhashps'], Decimal('0.003333333333333334')) assert_equal(mining_info['pooledtx'], 0)