0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-08 10:31:50 -05:00

Merge bitcoin/bitcoin#29021: refactor: rpc: Pass CBlockIndex by reference instead of pointer

fa5989d514 refactor: rpc: Pass CBlockIndex by reference instead of pointer (MarcoFalke)
fa604eb6cf refactor: Use reference instead of pointer in IsBlockPruned (MarcoFalke)

Pull request description:

  Follow-up to https://github.com/bitcoin/bitcoin/pull/29003#issuecomment-1841435462

ACKs for top commit:
  TheCharlatan:
    ACK fa5989d514
  pablomartin4btc:
    tACK fa5989d514
  dergoegge:
    Code review ACK fa5989d514

Tree-SHA512: 7449de3e3bb435dcbf438df88df343bb70f6edc3228ee7c0078f912ffb415e951ba30f8ecad916765f8cf896f0d784fe30535c5cf997e303cf5af257ade69773
This commit is contained in:
fanquake 2023-12-12 10:30:06 +00:00
commit 622e79e0fb
No known key found for this signature in database
GPG key ID: 2EEB9F5CC09526C1
9 changed files with 58 additions and 62 deletions

View file

@ -41,7 +41,7 @@ static void BlockToJsonVerbose(benchmark::Bench& bench)
{ {
TestBlockAndIndex data; TestBlockAndIndex data;
bench.run([&] { 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);
ankerl::nanobench::doNotOptimizeAway(univalue); ankerl::nanobench::doNotOptimizeAway(univalue);
}); });
} }
@ -51,7 +51,7 @@ BENCHMARK(BlockToJsonVerbose, benchmark::PriorityLevel::HIGH);
static void BlockToJsonVerboseWrite(benchmark::Bench& bench) static void BlockToJsonVerboseWrite(benchmark::Bench& bench)
{ {
TestBlockAndIndex data; TestBlockAndIndex data;
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);
bench.run([&] { bench.run([&] {
auto str = univalue.write(); auto str = univalue.write();
ankerl::nanobench::doNotOptimizeAway(str); ankerl::nanobench::doNotOptimizeAway(str);

View file

@ -582,10 +582,10 @@ const CBlockIndex* BlockManager::GetLastCheckpoint(const CCheckpointData& data)
return nullptr; return nullptr;
} }
bool BlockManager::IsBlockPruned(const CBlockIndex* pblockindex) bool BlockManager::IsBlockPruned(const CBlockIndex& block)
{ {
AssertLockHeld(::cs_main); AssertLockHeld(::cs_main);
return (m_have_pruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0); return m_have_pruned && !(block.nStatus & BLOCK_HAVE_DATA) && (block.nTx > 0);
} }
const CBlockIndex* BlockManager::GetFirstStoredBlock(const CBlockIndex& upper_block, const CBlockIndex* lower_block) const CBlockIndex* BlockManager::GetFirstStoredBlock(const CBlockIndex& upper_block, const CBlockIndex* lower_block)

View file

@ -344,7 +344,7 @@ public:
bool m_have_pruned = false; bool m_have_pruned = false;
//! Check whether the block associated with this index entry is pruned or not. //! Check whether the block associated with this index entry is pruned or not.
bool IsBlockPruned(const CBlockIndex* pblockindex) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); bool IsBlockPruned(const CBlockIndex& block) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
//! Create or update a prune lock identified by its name //! Create or update a prune lock identified by its name
void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);

View file

@ -264,7 +264,7 @@ static bool rest_headers(const std::any& context,
case RESTResponseFormat::JSON: { case RESTResponseFormat::JSON: {
UniValue jsonHeaders(UniValue::VARR); UniValue jsonHeaders(UniValue::VARR);
for (const CBlockIndex *pindex : headers) { for (const CBlockIndex *pindex : headers) {
jsonHeaders.push_back(blockheaderToJSON(tip, pindex)); jsonHeaders.push_back(blockheaderToJSON(*tip, *pindex));
} }
std::string strJSON = jsonHeaders.write() + "\n"; std::string strJSON = jsonHeaders.write() + "\n";
req->WriteHeader("Content-Type", "application/json"); req->WriteHeader("Content-Type", "application/json");
@ -304,10 +304,9 @@ static bool rest_block(const std::any& context,
if (!pblockindex) { if (!pblockindex) {
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
} }
if (chainman.m_blockman.IsBlockPruned(*pblockindex)) {
if (chainman.m_blockman.IsBlockPruned(pblockindex))
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)"); return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)");
}
} }
if (!chainman.m_blockman.ReadBlockFromDisk(block, *pblockindex)) { if (!chainman.m_blockman.ReadBlockFromDisk(block, *pblockindex)) {
@ -334,7 +333,7 @@ static bool rest_block(const std::any& context,
} }
case RESTResponseFormat::JSON: { case RESTResponseFormat::JSON: {
UniValue objBlock = blockToJSON(chainman.m_blockman, block, tip, pblockindex, tx_verbosity); UniValue objBlock = blockToJSON(chainman.m_blockman, block, *tip, *pblockindex, tx_verbosity);
std::string strJSON = objBlock.write() + "\n"; std::string strJSON = objBlock.write() + "\n";
req->WriteHeader("Content-Type", "application/json"); req->WriteHeader("Content-Type", "application/json");
req->WriteReply(HTTP_OK, strJSON); req->WriteReply(HTTP_OK, strJSON);

View file

@ -73,13 +73,11 @@ static CUpdatedBlock latestblock GUARDED_BY(cs_blockchange);
/* Calculate the difficulty for a given block index. /* Calculate the difficulty for a given block index.
*/ */
double GetDifficulty(const CBlockIndex* blockindex) double GetDifficulty(const CBlockIndex& blockindex)
{ {
CHECK_NONFATAL(blockindex); int nShift = (blockindex.nBits >> 24) & 0xff;
int nShift = (blockindex->nBits >> 24) & 0xff;
double dDiff = double dDiff =
(double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff); (double)0x0000ffff / (double)(blockindex.nBits & 0x00ffffff);
while (nShift < 29) while (nShift < 29)
{ {
@ -95,14 +93,14 @@ double GetDifficulty(const CBlockIndex* blockindex)
return dDiff; return dDiff;
} }
static int ComputeNextBlockAndDepth(const CBlockIndex* tip, const CBlockIndex* blockindex, const CBlockIndex*& next) static int ComputeNextBlockAndDepth(const CBlockIndex& tip, const CBlockIndex& blockindex, const CBlockIndex*& next)
{ {
next = tip->GetAncestor(blockindex->nHeight + 1); next = tip.GetAncestor(blockindex.nHeight + 1);
if (next && next->pprev == blockindex) { if (next && next->pprev == &blockindex) {
return tip->nHeight - blockindex->nHeight + 1; return tip.nHeight - blockindex.nHeight + 1;
} }
next = nullptr; next = nullptr;
return blockindex == tip ? 1 : -1; return &blockindex == &tip ? 1 : -1;
} }
static const CBlockIndex* ParseHashOrHeight(const UniValue& param, ChainstateManager& chainman) static const CBlockIndex* ParseHashOrHeight(const UniValue& param, ChainstateManager& chainman)
@ -133,36 +131,36 @@ static const CBlockIndex* ParseHashOrHeight(const UniValue& param, ChainstateMan
} }
} }
UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex) UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex)
{ {
// Serialize passed information without accessing chain state of the active chain! // Serialize passed information without accessing chain state of the active chain!
AssertLockNotHeld(cs_main); // For performance reasons AssertLockNotHeld(cs_main); // For performance reasons
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
result.pushKV("hash", blockindex->GetBlockHash().GetHex()); result.pushKV("hash", blockindex.GetBlockHash().GetHex());
const CBlockIndex* pnext; const CBlockIndex* pnext;
int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext); int confirmations = ComputeNextBlockAndDepth(tip, blockindex, pnext);
result.pushKV("confirmations", confirmations); result.pushKV("confirmations", confirmations);
result.pushKV("height", blockindex->nHeight); result.pushKV("height", blockindex.nHeight);
result.pushKV("version", blockindex->nVersion); result.pushKV("version", blockindex.nVersion);
result.pushKV("versionHex", strprintf("%08x", blockindex->nVersion)); result.pushKV("versionHex", strprintf("%08x", blockindex.nVersion));
result.pushKV("merkleroot", blockindex->hashMerkleRoot.GetHex()); result.pushKV("merkleroot", blockindex.hashMerkleRoot.GetHex());
result.pushKV("time", (int64_t)blockindex->nTime); result.pushKV("time", blockindex.nTime);
result.pushKV("mediantime", (int64_t)blockindex->GetMedianTimePast()); result.pushKV("mediantime", blockindex.GetMedianTimePast());
result.pushKV("nonce", (uint64_t)blockindex->nNonce); result.pushKV("nonce", blockindex.nNonce);
result.pushKV("bits", strprintf("%08x", blockindex->nBits)); result.pushKV("bits", strprintf("%08x", blockindex.nBits));
result.pushKV("difficulty", GetDifficulty(blockindex)); result.pushKV("difficulty", GetDifficulty(blockindex));
result.pushKV("chainwork", blockindex->nChainWork.GetHex()); result.pushKV("chainwork", blockindex.nChainWork.GetHex());
result.pushKV("nTx", (uint64_t)blockindex->nTx); result.pushKV("nTx", blockindex.nTx);
if (blockindex->pprev) if (blockindex.pprev)
result.pushKV("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()); result.pushKV("previousblockhash", blockindex.pprev->GetBlockHash().GetHex());
if (pnext) if (pnext)
result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex()); result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex());
return result; 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)
{ {
UniValue result = blockheaderToJSON(tip, blockindex); UniValue result = blockheaderToJSON(tip, blockindex);
@ -182,7 +180,7 @@ UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIn
case TxVerbosity::SHOW_DETAILS_AND_PREVOUT: case TxVerbosity::SHOW_DETAILS_AND_PREVOUT:
CBlockUndo blockUndo; CBlockUndo blockUndo;
const bool is_not_pruned{WITH_LOCK(::cs_main, return !blockman.IsBlockPruned(blockindex))}; const bool is_not_pruned{WITH_LOCK(::cs_main, return !blockman.IsBlockPruned(blockindex))};
const bool have_undo{is_not_pruned && blockman.UndoReadFromDisk(blockUndo, *blockindex)}; const bool have_undo{is_not_pruned && blockman.UndoReadFromDisk(blockUndo, blockindex)};
for (size_t i = 0; i < block.vtx.size(); ++i) { for (size_t i = 0; i < block.vtx.size(); ++i) {
const CTransactionRef& tx = block.vtx.at(i); const CTransactionRef& tx = block.vtx.at(i);
@ -418,7 +416,7 @@ static RPCHelpMan getdifficulty()
{ {
ChainstateManager& chainman = EnsureAnyChainman(request.context); ChainstateManager& chainman = EnsureAnyChainman(request.context);
LOCK(cs_main); LOCK(cs_main);
return GetDifficulty(chainman.ActiveChain().Tip()); return GetDifficulty(*CHECK_NONFATAL(chainman.ActiveChain().Tip()));
}, },
}; };
} }
@ -571,22 +569,22 @@ static RPCHelpMan getblockheader()
return strHex; return strHex;
} }
return blockheaderToJSON(tip, pblockindex); return blockheaderToJSON(*tip, *pblockindex);
}, },
}; };
} }
static CBlock GetBlockChecked(BlockManager& blockman, const CBlockIndex* pblockindex) static CBlock GetBlockChecked(BlockManager& blockman, const CBlockIndex& blockindex)
{ {
CBlock block; CBlock block;
{ {
LOCK(cs_main); LOCK(cs_main);
if (blockman.IsBlockPruned(pblockindex)) { if (blockman.IsBlockPruned(blockindex)) {
throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)"); throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)");
} }
} }
if (!blockman.ReadBlockFromDisk(block, *pblockindex)) { if (!blockman.ReadBlockFromDisk(block, blockindex)) {
// Block not found on disk. This could be because we have the block // Block not found on disk. This could be because we have the block
// header in our index but not yet have the block or did not accept the // header in our index but not yet have the block or did not accept the
// block. Or if the block was pruned right after we released the lock above. // block. Or if the block was pruned right after we released the lock above.
@ -596,21 +594,21 @@ static CBlock GetBlockChecked(BlockManager& blockman, const CBlockIndex* pblocki
return block; return block;
} }
static CBlockUndo GetUndoChecked(BlockManager& blockman, const CBlockIndex* pblockindex) static CBlockUndo GetUndoChecked(BlockManager& blockman, const CBlockIndex& blockindex)
{ {
CBlockUndo blockUndo; CBlockUndo blockUndo;
// The Genesis block does not have undo data // The Genesis block does not have undo data
if (pblockindex->nHeight == 0) return blockUndo; if (blockindex.nHeight == 0) return blockUndo;
{ {
LOCK(cs_main); LOCK(cs_main);
if (blockman.IsBlockPruned(pblockindex)) { if (blockman.IsBlockPruned(blockindex)) {
throw JSONRPCError(RPC_MISC_ERROR, "Undo data not available (pruned data)"); throw JSONRPCError(RPC_MISC_ERROR, "Undo data not available (pruned data)");
} }
} }
if (!blockman.UndoReadFromDisk(blockUndo, *pblockindex)) { if (!blockman.UndoReadFromDisk(blockUndo, blockindex)) {
throw JSONRPCError(RPC_MISC_ERROR, "Can't read undo data from disk"); throw JSONRPCError(RPC_MISC_ERROR, "Can't read undo data from disk");
} }
@ -736,7 +734,7 @@ static RPCHelpMan getblock()
} }
} }
const CBlock block{GetBlockChecked(chainman.m_blockman, pblockindex)}; const CBlock block{GetBlockChecked(chainman.m_blockman, *pblockindex)};
if (verbosity <= 0) if (verbosity <= 0)
{ {
@ -755,7 +753,7 @@ static RPCHelpMan getblock()
tx_verbosity = TxVerbosity::SHOW_DETAILS_AND_PREVOUT; 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);
}, },
}; };
} }
@ -1257,7 +1255,7 @@ RPCHelpMan getblockchaininfo()
obj.pushKV("blocks", height); obj.pushKV("blocks", height);
obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1); obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);
obj.pushKV("bestblockhash", tip.GetBlockHash().GetHex()); obj.pushKV("bestblockhash", tip.GetBlockHash().GetHex());
obj.pushKV("difficulty", GetDifficulty(&tip)); obj.pushKV("difficulty", GetDifficulty(tip));
obj.pushKV("time", tip.GetBlockTime()); obj.pushKV("time", tip.GetBlockTime());
obj.pushKV("mediantime", tip.GetMedianTimePast()); obj.pushKV("mediantime", tip.GetMedianTimePast());
obj.pushKV("verificationprogress", GuessVerificationProgress(chainman.GetParams().TxData(), &tip)); obj.pushKV("verificationprogress", GuessVerificationProgress(chainman.GetParams().TxData(), &tip));
@ -1815,8 +1813,8 @@ static RPCHelpMan getblockstats()
} }
} }
const CBlock& block = GetBlockChecked(chainman.m_blockman, &pindex); const CBlock& block = GetBlockChecked(chainman.m_blockman, pindex);
const CBlockUndo& blockUndo = GetUndoChecked(chainman.m_blockman, &pindex); const CBlockUndo& blockUndo = GetUndoChecked(chainman.m_blockman, pindex);
const bool do_all = stats.size() == 0; // Calculate everything if nothing selected (default) const bool do_all = stats.size() == 0; // Calculate everything if nothing selected (default)
const bool do_mediantxsize = do_all || stats.count("mediantxsize") != 0; const bool do_mediantxsize = do_all || stats.count("mediantxsize") != 0;
@ -2275,8 +2273,8 @@ public:
static bool CheckBlockFilterMatches(BlockManager& blockman, const CBlockIndex& blockindex, const GCSFilter::ElementSet& needles) static bool CheckBlockFilterMatches(BlockManager& blockman, const CBlockIndex& blockindex, const GCSFilter::ElementSet& needles)
{ {
const CBlock block{GetBlockChecked(blockman, &blockindex)}; const CBlock block{GetBlockChecked(blockman, blockindex)};
const CBlockUndo block_undo{GetUndoChecked(blockman, &blockindex)}; const CBlockUndo block_undo{GetUndoChecked(blockman, blockindex)};
// Check if any of the outputs match the scriptPubKey // Check if any of the outputs match the scriptPubKey
for (const auto& tx : block.vtx) { for (const auto& tx : block.vtx) {
@ -2845,7 +2843,7 @@ return RPCHelpMan{
data.pushKV("blocks", (int)chain.Height()); data.pushKV("blocks", (int)chain.Height());
data.pushKV("bestblockhash", tip->GetBlockHash().GetHex()); data.pushKV("bestblockhash", tip->GetBlockHash().GetHex());
data.pushKV("difficulty", (double)GetDifficulty(tip)); data.pushKV("difficulty", GetDifficulty(*tip));
data.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip)); data.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip));
data.pushKV("coins_db_cache_bytes", cs.m_coinsdb_cache_size_bytes); data.pushKV("coins_db_cache_bytes", cs.m_coinsdb_cache_size_bytes);
data.pushKV("coins_tip_cache_bytes", cs.m_coinstip_cache_size_bytes); data.pushKV("coins_tip_cache_bytes", cs.m_coinstip_cache_size_bytes);

View file

@ -32,16 +32,16 @@ static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5;
* @return A floating point number that is a multiple of the main net minimum * @return A floating point number that is a multiple of the main net minimum
* difficulty (4295032833 hashes). * difficulty (4295032833 hashes).
*/ */
double GetDifficulty(const CBlockIndex* blockindex); double GetDifficulty(const CBlockIndex& blockindex);
/** Callback for when block tip changed. */ /** Callback for when block tip changed. */
void RPCNotifyBlockChange(const CBlockIndex*); void RPCNotifyBlockChange(const CBlockIndex*);
/** Block description to JSON */ /** 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) LOCKS_EXCLUDED(cs_main);
/** Block header to JSON */ /** Block header to JSON */
UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex) LOCKS_EXCLUDED(cs_main); UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex) LOCKS_EXCLUDED(cs_main);
/** Used by getblockstats to get feerates at different percentiles by weight */ /** 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); void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector<std::pair<CAmount, int64_t>>& scores, int64_t total_weight);

View file

@ -441,7 +441,7 @@ static RPCHelpMan getmininginfo()
obj.pushKV("blocks", active_chain.Height()); 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_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); if (BlockAssembler::m_last_block_num_txs) obj.pushKV("currentblocktx", *BlockAssembler::m_last_block_num_txs);
obj.pushKV("difficulty", (double)GetDifficulty(active_chain.Tip())); obj.pushKV("difficulty", GetDifficulty(*CHECK_NONFATAL(active_chain.Tip())));
obj.pushKV("networkhashps", getnetworkhashps().HandleRequest(request)); obj.pushKV("networkhashps", getnetworkhashps().HandleRequest(request));
obj.pushKV("pooledtx", (uint64_t)mempool.size()); obj.pushKV("pooledtx", (uint64_t)mempool.size());
obj.pushKV("chain", chainman.GetParams().GetChainTypeString()); obj.pushKV("chain", chainman.GetParams().GetChainTypeString());

View file

@ -394,18 +394,17 @@ static RPCHelpMan getrawtransaction()
// If request is verbosity >= 1 but no blockhash was given, then look up the blockindex // If request is verbosity >= 1 but no blockhash was given, then look up the blockindex
if (request.params[2].isNull()) { if (request.params[2].isNull()) {
LOCK(cs_main); LOCK(cs_main);
blockindex = chainman.m_blockman.LookupBlockIndex(hash_block); blockindex = chainman.m_blockman.LookupBlockIndex(hash_block); // May be nullptr for mempool transactions
} }
if (verbosity == 1 || !blockindex) { if (verbosity == 1) {
TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate()); TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate());
return result; return result;
} }
CBlockUndo blockUndo; CBlockUndo blockUndo;
CBlock block; CBlock block;
const bool is_block_pruned{WITH_LOCK(cs_main, return chainman.m_blockman.IsBlockPruned(blockindex))};
if (tx->IsCoinBase() || is_block_pruned || if (tx->IsCoinBase() || !blockindex || WITH_LOCK(::cs_main, return chainman.m_blockman.IsBlockPruned(*blockindex)) ||
!(chainman.m_blockman.UndoReadFromDisk(blockUndo, *blockindex) && chainman.m_blockman.ReadBlockFromDisk(block, *blockindex))) { !(chainman.m_blockman.UndoReadFromDisk(blockUndo, *blockindex) && chainman.m_blockman.ReadBlockFromDisk(block, *blockindex))) {
TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate()); TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate());
return result; return result;

View file

@ -41,7 +41,7 @@ static void RejectDifficultyMismatch(double difficulty, double expected_difficul
static void TestDifficulty(uint32_t nbits, double expected_difficulty) static void TestDifficulty(uint32_t nbits, double expected_difficulty)
{ {
CBlockIndex* block_index = CreateBlockIndexWithNbits(nbits); CBlockIndex* block_index = CreateBlockIndexWithNbits(nbits);
double difficulty = GetDifficulty(block_index); double difficulty = GetDifficulty(*block_index);
delete block_index; delete block_index;
RejectDifficultyMismatch(difficulty, expected_difficulty); RejectDifficultyMismatch(difficulty, expected_difficulty);