Compare commits

..

12 commits

Author SHA1 Message Date
Sjors Provoost
223e8bcb99
doc: add release notes
Co-Authored-By: tdb3 <106488469+tdb3@users.noreply.github.com>
2025-01-06 10:00:48 +01:00
tdb3
46758baa30
test: use DIFF_1_N_BITS in tool_signet_miner 2025-01-06 10:00:48 +01:00
Sjors Provoost
17b61834e4
test: check testnet4 difficulty adjustment 2025-01-06 10:00:47 +01:00
Sjors Provoost
d24d93fb93
rpc: add next to getmininginfo 2025-01-06 10:00:47 +01:00
Sjors Provoost
5c6c056a41
rpc: add target and bits to getchainstates 2025-01-06 10:00:47 +01:00
Sjors Provoost
b148bedf80
rpc: add target and bits to getblockchaininfo 2025-01-06 10:00:47 +01:00
Sjors Provoost
38e97d4640
rpc: add next to getdifficulty and gettarget
Obtain the difficulty / target for the next block without having to call getblocktemplate.
2025-01-03 11:15:25 +01:00
Sjors Provoost
a4786467e4
rpc: add target to getmininginfo result 2025-01-03 11:15:25 +01:00
Sjors Provoost
e4f02e5aca
Add target to getblock(header) in RPC and REST 2025-01-03 11:15:24 +01:00
Sjors Provoost
675f2055d8
rpc: gettarget 2025-01-03 10:58:02 +01:00
tdb3
a601c4d16e
test: use REGTEST_N_BITS in feature_block 2025-01-03 10:58:02 +01:00
Sjors Provoost
59a2fbf56e
test: add nBits coverage 2025-01-03 10:58:01 +01:00
7 changed files with 56 additions and 34 deletions

View file

@ -11,4 +11,4 @@ New RPCs
REST interface
---
- `GET /rest/block/<BLOCK-HASH>.json` and `GET /rest/headers/<BLOCK-HASH>.json` now return the current target in the `target` field
- `GET /rest/block/<BLOCK-HASH>` and `GET /rest/headers/<BLOCK-HASH>` now return the current target in the `target` field

View file

@ -225,10 +225,11 @@ static bool rest_headers(const std::any& context,
const CBlockIndex* tip = nullptr;
std::vector<const CBlockIndex*> headers;
headers.reserve(*parsed_count);
ChainstateManager* maybe_chainman = GetChainman(context, req);
if (!maybe_chainman) return false;
ChainstateManager& chainman = *maybe_chainman;
uint256 pow_limit;
{
ChainstateManager* maybe_chainman = GetChainman(context, req);
if (!maybe_chainman) return false;
ChainstateManager& chainman = *maybe_chainman;
LOCK(cs_main);
CChain& active_chain = chainman.ActiveChain();
tip = active_chain.Tip();
@ -240,6 +241,8 @@ static bool rest_headers(const std::any& context,
}
pindex = active_chain.Next(pindex);
}
pow_limit = chainman.GetParams().GetConsensus().powLimit;
}
switch (rf) {
@ -268,7 +271,7 @@ static bool rest_headers(const std::any& context,
case RESTResponseFormat::JSON: {
UniValue jsonHeaders(UniValue::VARR);
for (const CBlockIndex *pindex : headers) {
jsonHeaders.push_back(blockheaderToJSON(*tip, *pindex, chainman.GetConsensus().powLimit));
jsonHeaders.push_back(blockheaderToJSON(*tip, *pindex, pow_limit));
}
std::string strJSON = jsonHeaders.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
@ -302,6 +305,7 @@ static bool rest_block(const std::any& context,
ChainstateManager* maybe_chainman = GetChainman(context, req);
if (!maybe_chainman) return false;
ChainstateManager& chainman = *maybe_chainman;
uint256 pow_limit;
{
LOCK(cs_main);
tip = chainman.ActiveChain().Tip();
@ -316,6 +320,7 @@ static bool rest_block(const std::any& context,
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (not fully downloaded)");
}
pos = pblockindex->GetBlockPos();
pow_limit = chainman.GetParams().GetConsensus().powLimit;
}
std::vector<uint8_t> block_data{};
@ -341,7 +346,7 @@ static bool rest_block(const std::any& context,
CBlock block{};
DataStream block_stream{block_data};
block_stream >> TX_WITH_WITNESS(block);
UniValue objBlock = blockToJSON(chainman.m_blockman, block, *tip, *pblockindex, tx_verbosity, chainman.GetConsensus().powLimit);
UniValue objBlock = blockToJSON(chainman.m_blockman, block, *tip, *pblockindex, tx_verbosity, pow_limit);
std::string strJSON = objBlock.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
req->WriteReply(HTTP_OK, strJSON);

View file

@ -444,7 +444,9 @@ static RPCHelpMan getdifficulty()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
ChainstateManager& chainman = EnsureAnyChainman(request.context);
CBlockIndex& tip{*CHECK_NONFATAL(WITH_LOCK(chainman.GetMutex(), return chainman.ActiveChain().Tip()))};
LOCK(cs_main);
CBlockIndex* tip{CHECK_NONFATAL(chainman.ActiveChain().Tip())};
auto consensusParams{chainman.GetParams().GetConsensus()};
bool next{false};
if (!request.params[0].isNull()) {
@ -453,10 +455,10 @@ static RPCHelpMan getdifficulty()
if (next) {
CBlockIndex next_index;
NextEmptyBlockIndex(tip, chainman.GetConsensus(), next_index);
NextEmptyBlockIndex(tip, consensusParams, next_index);
return GetDifficulty(next_index);
} else {
return GetDifficulty(tip);
return GetDifficulty(*tip);
}
},
@ -479,7 +481,9 @@ static RPCHelpMan gettarget()
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
ChainstateManager& chainman = EnsureAnyChainman(request.context);
CBlockIndex& tip{*CHECK_NONFATAL(WITH_LOCK(chainman.GetMutex(), return chainman.ActiveChain().Tip()))};
LOCK(cs_main);
CBlockIndex* tip{CHECK_NONFATAL(chainman.ActiveChain().Tip())};
auto consensusParams{chainman.GetParams().GetConsensus()};
bool next{false};
if (!request.params[0].isNull()) {
@ -488,10 +492,10 @@ static RPCHelpMan gettarget()
if (next) {
CBlockIndex next_index;
NextEmptyBlockIndex(tip, chainman.GetConsensus(), next_index);
return GetTarget(next_index, chainman.GetConsensus().powLimit).GetHex();
NextEmptyBlockIndex(tip, consensusParams, next_index);
return GetTarget(next_index, consensusParams.powLimit).GetHex();
} else {
return GetTarget(tip, chainman.GetConsensus().powLimit).GetHex();
return GetTarget(*tip, consensusParams.powLimit).GetHex();
}
},
};
@ -628,11 +632,16 @@ static RPCHelpMan getblockheader()
const CBlockIndex* pblockindex;
const CBlockIndex* tip;
ChainstateManager& chainman = EnsureAnyChainman(request.context);
uint256 pow_limit;
{
ChainstateManager& chainman = EnsureAnyChainman(request.context);
LOCK(cs_main);
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
tip = chainman.ActiveChain().Tip();
// Now that we have a lock on cs_main, get powLimit so blockToJSON()
// doesn't have to.
pow_limit = chainman.GetParams().GetConsensus().powLimit;
}
if (!pblockindex) {
@ -647,7 +656,7 @@ static RPCHelpMan getblockheader()
return strHex;
}
return blockheaderToJSON(*tip, *pblockindex, chainman.GetConsensus().powLimit);
return blockheaderToJSON(*tip, *pblockindex, pow_limit);
},
};
}
@ -824,6 +833,7 @@ static RPCHelpMan getblock()
const CBlockIndex* pblockindex;
const CBlockIndex* tip;
uint256 pow_limit;
ChainstateManager& chainman = EnsureAnyChainman(request.context);
{
LOCK(cs_main);
@ -833,6 +843,10 @@ static RPCHelpMan getblock()
if (!pblockindex) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
// Now that we have a lock on cs_main, get powLimit so blockToJSON()
// doesn't have to.
pow_limit = chainman.GetParams().GetConsensus().powLimit;
}
const std::vector<uint8_t> block_data{GetRawBlockChecked(chainman.m_blockman, *pblockindex)};
@ -854,7 +868,7 @@ static RPCHelpMan getblock()
tx_verbosity = TxVerbosity::SHOW_DETAILS_AND_PREVOUT;
}
return blockToJSON(chainman.m_blockman, block, *tip, *pblockindex, tx_verbosity, chainman.GetConsensus().powLimit);
return blockToJSON(chainman.m_blockman, block, *tip, *pblockindex, tx_verbosity, pow_limit);
},
};
}
@ -1383,13 +1397,14 @@ RPCHelpMan getblockchaininfo()
const CBlockIndex& tip{*CHECK_NONFATAL(active_chainstate.m_chain.Tip())};
const int height{tip.nHeight};
uint256 pow_limit{chainman.GetParams().GetConsensus().powLimit};
UniValue obj(UniValue::VOBJ);
obj.pushKV("chain", chainman.GetParams().GetChainTypeString());
obj.pushKV("blocks", height);
obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);
obj.pushKV("bestblockhash", tip.GetBlockHash().GetHex());
obj.pushKV("bits", strprintf("%08x", tip.nBits));
obj.pushKV("target", GetTarget(tip, chainman.GetConsensus().powLimit).GetHex());
obj.pushKV("target", GetTarget(tip, pow_limit).GetHex());
obj.pushKV("difficulty", GetDifficulty(tip));
obj.pushKV("time", tip.GetBlockTime());
obj.pushKV("mediantime", tip.GetMedianTimePast());
@ -3398,11 +3413,12 @@ return RPCHelpMan{
}
const CChain& chain = cs.m_chain;
const CBlockIndex* tip = chain.Tip();
uint256 pow_limit{chainman.GetParams().GetConsensus().powLimit};
data.pushKV("blocks", (int)chain.Height());
data.pushKV("bestblockhash", tip->GetBlockHash().GetHex());
data.pushKV("bits", strprintf("%08x", tip->nBits));
data.pushKV("target", GetTarget(*tip, chainman.GetConsensus().powLimit).GetHex());
data.pushKV("target", GetTarget(*tip, pow_limit).GetHex());
data.pushKV("difficulty", GetDifficulty(*tip));
data.pushKV("verificationprogress", chainman.GuessVerificationProgress(tip));
data.pushKV("coins_db_cache_bytes", cs.m_coinsdb_cache_size_bytes);

View file

@ -454,33 +454,34 @@ static RPCHelpMan getmininginfo()
const CTxMemPool& mempool = EnsureMemPool(node);
ChainstateManager& chainman = EnsureChainman(node);
LOCK(cs_main);
auto consensusParams{chainman.GetParams().GetConsensus()};
const CChain& active_chain = chainman.ActiveChain();
CBlockIndex& tip{*CHECK_NONFATAL(active_chain.Tip())};
CBlockIndex* tip{CHECK_NONFATAL(active_chain.Tip())};
UniValue obj(UniValue::VOBJ);
obj.pushKV("blocks", active_chain.Height());
if (BlockAssembler::m_last_block_weight) obj.pushKV("currentblockweight", *BlockAssembler::m_last_block_weight);
if (BlockAssembler::m_last_block_num_txs) obj.pushKV("currentblocktx", *BlockAssembler::m_last_block_num_txs);
obj.pushKV("bits", strprintf("%08x", tip.nBits));
obj.pushKV("difficulty", GetDifficulty(tip));
obj.pushKV("target", GetTarget(tip, chainman.GetConsensus().powLimit).GetHex());
obj.pushKV("bits", strprintf("%08x", tip->nBits));
obj.pushKV("difficulty", GetDifficulty(*tip));
obj.pushKV("target", GetTarget(*tip, consensusParams.powLimit).GetHex());
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);
NextEmptyBlockIndex(tip, consensusParams, 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());
next.pushKV("target", GetTarget(next_index,consensusParams.powLimit).GetHex());
obj.pushKV("next", next);
if (chainman.GetParams().GetChainType() == ChainType::SIGNET) {
const std::vector<uint8_t>& signet_challenge =
chainman.GetConsensus().signet_challenge;
consensusParams.signet_challenge;
obj.pushKV("signet_challenge", HexStr(signet_challenge));
}
obj.pushKV("warnings", node::GetWarningsForRpc(*CHECK_NONFATAL(node.warnings), IsDeprecatedRPCEnabled("warnings")));

View file

@ -4,7 +4,7 @@
#include <rpc/server_util.h>
#include <chain.h>
#include <chain.h> // for CBlockIndex
#include <common/args.h>
#include <net_processing.h>
#include <node/context.h>
@ -134,17 +134,17 @@ AddrMan& EnsureAnyAddrman(const std::any& context)
return EnsureAddrman(EnsureAnyNodeContext(context));
}
void NextEmptyBlockIndex(CBlockIndex& tip, const Consensus::Params& consensusParams, CBlockIndex& next_index)
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.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.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;
next_index.nHeight = tip->nHeight + 1;
}

View file

@ -43,6 +43,6 @@ 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);
void NextEmptyBlockIndex(CBlockIndex* tip, const Consensus::Params& consensusParams, CBlockIndex& next_index);
#endif // BITCOIN_RPC_SERVER_UTIL_H

View file

@ -4,7 +4,7 @@
#include <bitcoin-build-config.h> // IWYU pragma: keep
#include <chain.h>
#include <chain.h> // for CBlockIndex
#include <clientversion.h>
#include <common/args.h>
#include <common/messages.h>