mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-02 14:37:42 -03:00
rpc: add next to getdifficulty and gettarget
Obtain the difficulty / target for the next block without having to call getblocktemplate.
This commit is contained in:
parent
f06f55090e
commit
1502b98b8b
5 changed files with 64 additions and 5 deletions
|
@ -432,7 +432,9 @@ static RPCHelpMan getdifficulty()
|
||||||
{
|
{
|
||||||
return RPCHelpMan{"getdifficulty",
|
return RPCHelpMan{"getdifficulty",
|
||||||
"\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n",
|
"\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n",
|
||||||
{},
|
{
|
||||||
|
{"next", RPCArg::Type::BOOL, RPCArg::Default{false}, "difficulty for the next block, if found now"},
|
||||||
|
},
|
||||||
RPCResult{
|
RPCResult{
|
||||||
RPCResult::Type::NUM, "", "the proof-of-work difficulty as a multiple of the minimum difficulty."},
|
RPCResult::Type::NUM, "", "the proof-of-work difficulty as a multiple of the minimum difficulty."},
|
||||||
RPCExamples{
|
RPCExamples{
|
||||||
|
@ -442,8 +444,21 @@ static RPCHelpMan getdifficulty()
|
||||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
|
||||||
{
|
{
|
||||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||||
LOCK(cs_main);
|
CBlockIndex& tip{*CHECK_NONFATAL(WITH_LOCK(chainman.GetMutex(), return chainman.ActiveChain().Tip()))};
|
||||||
return GetDifficulty(*CHECK_NONFATAL(chainman.ActiveChain().Tip()));
|
|
||||||
|
bool next{false};
|
||||||
|
if (!request.params[0].isNull()) {
|
||||||
|
next = request.params[0].get_bool();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next) {
|
||||||
|
CBlockIndex next_index;
|
||||||
|
NextEmptyBlockIndex(tip, chainman.GetConsensus(), next_index);
|
||||||
|
return GetDifficulty(next_index);
|
||||||
|
} else {
|
||||||
|
return GetDifficulty(tip);
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -452,7 +467,9 @@ static RPCHelpMan gettarget()
|
||||||
{
|
{
|
||||||
return RPCHelpMan{"gettarget",
|
return RPCHelpMan{"gettarget",
|
||||||
"\nReturns the proof-of-work target.\n",
|
"\nReturns the proof-of-work target.\n",
|
||||||
{},
|
{
|
||||||
|
{"next", RPCArg::Type::BOOL, RPCArg::Default{false}, "target for the next block, if found now"},
|
||||||
|
},
|
||||||
RPCResult{
|
RPCResult{
|
||||||
RPCResult::Type::STR_HEX, "", "the proof-of-work target."},
|
RPCResult::Type::STR_HEX, "", "the proof-of-work target."},
|
||||||
RPCExamples{
|
RPCExamples{
|
||||||
|
@ -463,7 +480,19 @@ static RPCHelpMan gettarget()
|
||||||
{
|
{
|
||||||
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
ChainstateManager& chainman = EnsureAnyChainman(request.context);
|
||||||
CBlockIndex& tip{*CHECK_NONFATAL(WITH_LOCK(chainman.GetMutex(), return chainman.ActiveChain().Tip()))};
|
CBlockIndex& tip{*CHECK_NONFATAL(WITH_LOCK(chainman.GetMutex(), return chainman.ActiveChain().Tip()))};
|
||||||
return GetTarget(tip, chainman.GetParams().GetConsensus().powLimit).GetHex();
|
|
||||||
|
bool next{false};
|
||||||
|
if (!request.params[0].isNull()) {
|
||||||
|
next = request.params[0].get_bool();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next) {
|
||||||
|
CBlockIndex next_index;
|
||||||
|
NextEmptyBlockIndex(tip, chainman.GetConsensus(), next_index);
|
||||||
|
return GetTarget(next_index, chainman.GetConsensus().powLimit).GetHex();
|
||||||
|
} else {
|
||||||
|
return GetTarget(tip, chainman.GetConsensus().powLimit).GetHex();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,6 +114,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||||
{ "getblock", 1, "verbose" },
|
{ "getblock", 1, "verbose" },
|
||||||
{ "getblockheader", 1, "verbose" },
|
{ "getblockheader", 1, "verbose" },
|
||||||
{ "getchaintxstats", 0, "nblocks" },
|
{ "getchaintxstats", 0, "nblocks" },
|
||||||
|
{ "getdifficulty", 0, "next" },
|
||||||
|
{ "gettarget", 0, "next" },
|
||||||
{ "gettransaction", 1, "include_watchonly" },
|
{ "gettransaction", 1, "include_watchonly" },
|
||||||
{ "gettransaction", 2, "verbose" },
|
{ "gettransaction", 2, "verbose" },
|
||||||
{ "getrawtransaction", 1, "verbosity" },
|
{ "getrawtransaction", 1, "verbosity" },
|
||||||
|
|
|
@ -4,10 +4,13 @@
|
||||||
|
|
||||||
#include <rpc/server_util.h>
|
#include <rpc/server_util.h>
|
||||||
|
|
||||||
|
#include <chain.h>
|
||||||
#include <common/args.h>
|
#include <common/args.h>
|
||||||
#include <net_processing.h>
|
#include <net_processing.h>
|
||||||
#include <node/context.h>
|
#include <node/context.h>
|
||||||
|
#include <node/miner.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
|
#include <pow.h>
|
||||||
#include <rpc/protocol.h>
|
#include <rpc/protocol.h>
|
||||||
#include <rpc/request.h>
|
#include <rpc/request.h>
|
||||||
#include <txmempool.h>
|
#include <txmempool.h>
|
||||||
|
@ -17,6 +20,7 @@
|
||||||
#include <any>
|
#include <any>
|
||||||
|
|
||||||
using node::NodeContext;
|
using node::NodeContext;
|
||||||
|
using node::UpdateTime;
|
||||||
|
|
||||||
NodeContext& EnsureAnyNodeContext(const std::any& context)
|
NodeContext& EnsureAnyNodeContext(const std::any& context)
|
||||||
{
|
{
|
||||||
|
@ -129,3 +133,18 @@ AddrMan& EnsureAnyAddrman(const std::any& context)
|
||||||
{
|
{
|
||||||
return EnsureAddrman(EnsureAnyNodeContext(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;
|
||||||
|
}
|
||||||
|
|
|
@ -7,8 +7,11 @@
|
||||||
|
|
||||||
#include <any>
|
#include <any>
|
||||||
|
|
||||||
|
#include <consensus/params.h>
|
||||||
|
|
||||||
class AddrMan;
|
class AddrMan;
|
||||||
class ArgsManager;
|
class ArgsManager;
|
||||||
|
class CBlockIndex;
|
||||||
class CBlockPolicyEstimator;
|
class CBlockPolicyEstimator;
|
||||||
class CConnman;
|
class CConnman;
|
||||||
class CTxMemPool;
|
class CTxMemPool;
|
||||||
|
@ -39,4 +42,7 @@ PeerManager& EnsurePeerman(const node::NodeContext& node);
|
||||||
AddrMan& EnsureAddrman(const node::NodeContext& node);
|
AddrMan& EnsureAddrman(const node::NodeContext& node);
|
||||||
AddrMan& EnsureAnyAddrman(const std::any& context);
|
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
|
#endif // BITCOIN_RPC_SERVER_UTIL_H
|
||||||
|
|
|
@ -444,11 +444,14 @@ class BlockchainTest(BitcoinTestFramework):
|
||||||
# 1 hash in 2 should be valid, so difficulty should be 1/2**31
|
# 1 hash in 2 should be valid, so difficulty should be 1/2**31
|
||||||
# binary => decimal => binary math is why we do this check
|
# binary => decimal => binary math is why we do this check
|
||||||
assert abs(difficulty * 2**31 - 1) < 0.0001
|
assert abs(difficulty * 2**31 - 1) < 0.0001
|
||||||
|
self.log.info("Next difficulty should be the same as the current (no difficulty adjustment)")
|
||||||
|
assert_equal(self.nodes[0].getdifficulty(next=True), difficulty)
|
||||||
|
|
||||||
def _test_gettarget(self):
|
def _test_gettarget(self):
|
||||||
self.log.info("Test gettarget")
|
self.log.info("Test gettarget")
|
||||||
target = self.nodes[0].gettarget()
|
target = self.nodes[0].gettarget()
|
||||||
assert_equal(target, target_str(REGTEST_TARGET))
|
assert_equal(target, target_str(REGTEST_TARGET))
|
||||||
|
assert_equal(self.nodes[0].gettarget(next=True), target_str(REGTEST_TARGET))
|
||||||
|
|
||||||
def _test_getnetworkhashps(self):
|
def _test_getnetworkhashps(self):
|
||||||
self.log.info("Test getnetworkhashps")
|
self.log.info("Test getnetworkhashps")
|
||||||
|
|
Loading…
Add table
Reference in a new issue