Skip to content

Commit

Permalink
Add target to getblock(header) in RPC and REST
Browse files Browse the repository at this point in the history
  • Loading branch information
Sjors committed Jan 22, 2025
1 parent 341f932 commit 2a7bfeb
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 16 deletions.
6 changes: 4 additions & 2 deletions src/bench/rpc_blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ struct TestBlockAndIndex {
static void BlockToJsonVerbose(benchmark::Bench& bench)
{
TestBlockAndIndex data;
const uint256 pow_limit{data.testing_setup->m_node.chainman->GetParams().GetConsensus().powLimit};
bench.run([&] {
auto univalue = blockToJSON(data.testing_setup->m_node.chainman->m_blockman, data.block, data.blockindex, data.blockindex, TxVerbosity::SHOW_DETAILS_AND_PREVOUT);
auto univalue = blockToJSON(data.testing_setup->m_node.chainman->m_blockman, data.block, data.blockindex, data.blockindex, TxVerbosity::SHOW_DETAILS_AND_PREVOUT, pow_limit);
ankerl::nanobench::doNotOptimizeAway(univalue);
});
}
Expand All @@ -59,7 +60,8 @@ BENCHMARK(BlockToJsonVerbose, benchmark::PriorityLevel::HIGH);
static void BlockToJsonVerboseWrite(benchmark::Bench& bench)
{
TestBlockAndIndex data;
auto univalue = blockToJSON(data.testing_setup->m_node.chainman->m_blockman, data.block, data.blockindex, data.blockindex, TxVerbosity::SHOW_DETAILS_AND_PREVOUT);
const uint256 pow_limit{data.testing_setup->m_node.chainman->GetParams().GetConsensus().powLimit};
auto univalue = blockToJSON(data.testing_setup->m_node.chainman->m_blockman, data.block, data.blockindex, data.blockindex, TxVerbosity::SHOW_DETAILS_AND_PREVOUT, pow_limit);
bench.run([&] {
auto str = univalue.write();
ankerl::nanobench::doNotOptimizeAway(str);
Expand Down
10 changes: 5 additions & 5 deletions src/rest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,10 @@ 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;
{
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();
Expand Down Expand Up @@ -268,7 +268,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));
jsonHeaders.push_back(blockheaderToJSON(*tip, *pindex, chainman.GetConsensus().powLimit));
}
std::string strJSON = jsonHeaders.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
Expand Down Expand Up @@ -341,7 +341,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);
UniValue objBlock = blockToJSON(chainman.m_blockman, block, *tip, *pblockindex, tx_verbosity, chainman.GetConsensus().powLimit);
std::string strJSON = objBlock.write() + "\n";
req->WriteHeader("Content-Type", "application/json");
req->WriteReply(HTTP_OK, strJSON);
Expand Down
15 changes: 9 additions & 6 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ static const CBlockIndex* ParseHashOrHeight(const UniValue& param, ChainstateMan
}
}

UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex)
UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex, const uint256 pow_limit)
{
// Serialize passed information without accessing chain state of the active chain!
AssertLockNotHeld(cs_main); // For performance reasons
Expand All @@ -164,6 +164,7 @@ UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex
result.pushKV("mediantime", blockindex.GetMedianTimePast());
result.pushKV("nonce", blockindex.nNonce);
result.pushKV("bits", strprintf("%08x", blockindex.nBits));
result.pushKV("target", GetTarget(tip, pow_limit).GetHex());
result.pushKV("difficulty", GetDifficulty(blockindex));
result.pushKV("chainwork", blockindex.nChainWork.GetHex());
result.pushKV("nTx", blockindex.nTx);
Expand All @@ -175,9 +176,9 @@ UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex
return result;
}

UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIndex& tip, const CBlockIndex& blockindex, TxVerbosity verbosity)
UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIndex& tip, const CBlockIndex& blockindex, TxVerbosity verbosity, const uint256 pow_limit)
{
UniValue result = blockheaderToJSON(tip, blockindex);
UniValue result = blockheaderToJSON(tip, blockindex, pow_limit);

result.pushKV("strippedsize", (int)::GetSerializeSize(TX_NO_WITNESS(block)));
result.pushKV("size", (int)::GetSerializeSize(TX_WITH_WITNESS(block)));
Expand Down Expand Up @@ -554,6 +555,7 @@ static RPCHelpMan getblockheader()
{RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in " + UNIX_EPOCH_TIME},
{RPCResult::Type::NUM, "nonce", "The nonce"},
{RPCResult::Type::STR_HEX, "bits", "nBits: compact representation of the block difficulty target"},
{RPCResult::Type::STR_HEX, "target", "The difficulty target"},
{RPCResult::Type::NUM, "difficulty", "The difficulty"},
{RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the current chain"},
{RPCResult::Type::NUM, "nTx", "The number of transactions in the block"},
Expand All @@ -577,8 +579,8 @@ static RPCHelpMan getblockheader()

const CBlockIndex* pblockindex;
const CBlockIndex* tip;
ChainstateManager& chainman = EnsureAnyChainman(request.context);
{
ChainstateManager& chainman = EnsureAnyChainman(request.context);
LOCK(cs_main);
pblockindex = chainman.m_blockman.LookupBlockIndex(hash);
tip = chainman.ActiveChain().Tip();
Expand All @@ -596,7 +598,7 @@ static RPCHelpMan getblockheader()
return strHex;
}

return blockheaderToJSON(*tip, *pblockindex);
return blockheaderToJSON(*tip, *pblockindex, chainman.GetConsensus().powLimit);
},
};
}
Expand Down Expand Up @@ -728,6 +730,7 @@ static RPCHelpMan getblock()
{RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in " + UNIX_EPOCH_TIME},
{RPCResult::Type::NUM, "nonce", "The nonce"},
{RPCResult::Type::STR_HEX, "bits", "nBits: compact representation of the block difficulty target"},
{RPCResult::Type::STR_HEX, "target", "The difficulty target"},
{RPCResult::Type::NUM, "difficulty", "The difficulty"},
{RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the chain up to this block (in hex)"},
{RPCResult::Type::NUM, "nTx", "The number of transactions in the block"},
Expand Down Expand Up @@ -802,7 +805,7 @@ static RPCHelpMan getblock()
tx_verbosity = TxVerbosity::SHOW_DETAILS_AND_PREVOUT;
}

return blockToJSON(chainman.m_blockman, block, *tip, *pblockindex, tx_verbosity);
return blockToJSON(chainman.m_blockman, block, *tip, *pblockindex, tx_verbosity, chainman.GetConsensus().powLimit);
},
};
}
Expand Down
4 changes: 2 additions & 2 deletions src/rpc/blockchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5;
double GetDifficulty(const CBlockIndex& blockindex);

/** Block description to JSON */
UniValue blockToJSON(node::BlockManager& blockman, const CBlock& block, const CBlockIndex& tip, const CBlockIndex& blockindex, TxVerbosity verbosity) LOCKS_EXCLUDED(cs_main);
UniValue blockToJSON(node::BlockManager& blockman, const CBlock& block, const CBlockIndex& tip, const CBlockIndex& blockindex, TxVerbosity verbosity, const uint256 pow_limit) LOCKS_EXCLUDED(cs_main);

/** Block header to JSON */
UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex) LOCKS_EXCLUDED(cs_main);
UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex, const uint256 pow_limit) LOCKS_EXCLUDED(cs_main);

/** Used by getblockstats to get feerates at different percentiles by weight */
void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector<std::pair<CAmount, int64_t>>& scores, int64_t total_weight);
Expand Down
2 changes: 1 addition & 1 deletion test/functional/interface_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ def run_test(self):

# Compare with normal RPC block response
rpc_block_json = self.nodes[0].getblock(bb_hash)
for key in ['hash', 'confirmations', 'height', 'version', 'merkleroot', 'time', 'nonce', 'bits', 'difficulty', 'chainwork', 'previousblockhash']:
for key in ['hash', 'confirmations', 'height', 'version', 'merkleroot', 'time', 'nonce', 'bits', 'target', 'difficulty', 'chainwork', 'previousblockhash']:
assert_equal(json_obj[0][key], rpc_block_json[key])

# See if we can get 5 headers in one response
Expand Down
3 changes: 3 additions & 0 deletions test/functional/rpc_blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
MAX_FUTURE_BLOCK_TIME,
TIME_GENESIS_BLOCK,
REGTEST_N_BITS,
REGTEST_TARGET,
create_block,
create_coinbase,
create_tx_with_script,
nbits_str,
target_str,
)
from test_framework.messages import (
CBlockHeader,
Expand Down Expand Up @@ -415,6 +417,7 @@ def _test_getblockheader(self):
assert_is_hash_string(header['previousblockhash'])
assert_is_hash_string(header['merkleroot'])
assert_equal(header['bits'], nbits_str(REGTEST_N_BITS))
assert_equal(header['target'], target_str(REGTEST_TARGET))
assert isinstance(header['time'], int)
assert_equal(header['mediantime'], TIME_RANGE_MTP)
assert isinstance(header['nonce'], int)
Expand Down
6 changes: 6 additions & 0 deletions test/functional/test_framework/blocktools.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
hash256,
ser_uint256,
tx_from_hex,
uint256_from_compact,
uint256_from_str,
WITNESS_SCALE_FACTOR,
)
Expand Down Expand Up @@ -66,10 +67,15 @@
MIN_BLOCKS_TO_KEEP = 288

REGTEST_N_BITS = 0x207fffff # difficulty retargeting is disabled in REGTEST chainparams"
REGTEST_TARGET = 0x7fffff0000000000000000000000000000000000000000000000000000000000
assert_equal(uint256_from_compact(REGTEST_N_BITS), REGTEST_TARGET)

def nbits_str(nbits):
return f"{nbits:08x}"

def target_str(target):
return f"{target:064x}"

def create_block(hashprev=None, coinbase=None, ntime=None, *, version=None, tmpl=None, txlist=None):
"""Create a block (with regtest difficulty)."""
block = CBlock()
Expand Down

0 comments on commit 2a7bfeb

Please sign in to comment.