mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-04 10:12:28 +02:00
rpc: fix race condition in gettxoutsetinfo
Fix an assertion failure in gettxoutsetinfo (issue #34263) caused by capturing the best block before releasing cs_main, then checking it against a potentially newer best block in GetUTXOStats(). Remove the early pindex capture since ComputeUTXOStats() independently fetches the current best block under lock. Use stats.hashBlock and stats.nHeight (the actual computed values) instead of the potentially stale pindex when building the response.
This commit is contained in:
@@ -1080,7 +1080,6 @@ static RPCHelpMan gettxoutsetinfo()
|
||||
LOCK(::cs_main);
|
||||
coins_view = &active_chainstate.CoinsDB();
|
||||
blockman = &active_chainstate.m_blockman;
|
||||
pindex = blockman->LookupBlockIndex(coins_view->GetBestBlock());
|
||||
}
|
||||
|
||||
if (!request.params[1].isNull()) {
|
||||
@@ -1104,7 +1103,7 @@ static RPCHelpMan gettxoutsetinfo()
|
||||
|
||||
// If a specific block was requested and the index has already synced past that height, we can return the
|
||||
// data already even though the index is not fully synced yet.
|
||||
if (pindex->nHeight > summary.best_block_height) {
|
||||
if (pindex && pindex->nHeight > summary.best_block_height) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, strprintf("Unable to get data because coinstatsindex is still syncing. Current height: %d", summary.best_block_height));
|
||||
}
|
||||
}
|
||||
@@ -1130,8 +1129,9 @@ static RPCHelpMan gettxoutsetinfo()
|
||||
ret.pushKV("disk_size", stats.nDiskSize);
|
||||
} else {
|
||||
CCoinsStats prev_stats{};
|
||||
if (pindex->nHeight > 0) {
|
||||
const std::optional<CCoinsStats> maybe_prev_stats = GetUTXOStats(coins_view, *blockman, hash_type, node.rpc_interruption_point, pindex->pprev, index_requested);
|
||||
if (stats.nHeight > 0) {
|
||||
const CBlockIndex& block_index = *CHECK_NONFATAL(WITH_LOCK(::cs_main, return blockman->LookupBlockIndex(stats.hashBlock)));
|
||||
const std::optional<CCoinsStats> maybe_prev_stats = GetUTXOStats(coins_view, *blockman, hash_type, node.rpc_interruption_point, block_index.pprev, index_requested);
|
||||
if (!maybe_prev_stats) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user