Merge 30713 via rpc_scanblocks_status_results-28

This commit is contained in:
Luke Dashjr 2025-03-05 03:27:08 +00:00
commit 15e73d0eb8
2 changed files with 33 additions and 4 deletions

View File

@ -0,0 +1,5 @@
Updated RPCs
------------
- The `status` action of the`scanblocks` RPC now returns an additional array `relevant_blocks` containing
the matching block hashes found so far during a scan.

View File

@ -2518,9 +2518,17 @@ public:
return true;
}
void release() {
if (!m_could_reserve) {
throw std::runtime_error("Attempt to release unreserved BlockFiltersScanReserver");
}
g_scanfilter_in_progress = false;
m_could_reserve = false;
}
~BlockFiltersScanReserver() {
if (m_could_reserve) {
g_scanfilter_in_progress = false;
release();
}
}
};
@ -2580,6 +2588,9 @@ static RPCHelpMan scanblocks()
RPCResult{"when action=='status' and a scan is currently in progress", RPCResult::Type::OBJ, "", "", {
{RPCResult::Type::NUM, "progress", "Approximate percent complete"},
{RPCResult::Type::NUM, "current_height", "Height of the block currently being scanned"},
{RPCResult::Type::ARR, "relevant_blocks", "Blocks that may have matched a scanobject.", {
{RPCResult::Type::STR_HEX, "blockhash", "A relevant blockhash"},
}},
},
},
scan_result_abort,
@ -2594,15 +2605,20 @@ static RPCHelpMan scanblocks()
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
static GlobalMutex cs_relevant_blocks;
static UniValue relevant_blocks GUARDED_BY(cs_relevant_blocks);
UniValue ret(UniValue::VOBJ);
if (request.params[0].get_str() == "status") {
BlockFiltersScanReserver reserver;
LOCK(cs_relevant_blocks);
if (reserver.reserve()) {
// no scan in progress
return NullUniValue;
}
ret.pushKV("progress", g_scanfilter_progress.load());
ret.pushKV("current_height", g_scanfilter_progress_height.load());
ret.pushKV("relevant_blocks", relevant_blocks);
return ret;
} else if (request.params[0].get_str() == "abort") {
BlockFiltersScanReserver reserver;
@ -2614,6 +2630,11 @@ static RPCHelpMan scanblocks()
g_scanfilter_should_abort_scan = true;
return true;
} else if (request.params[0].get_str() == "start") {
{
LOCK(cs_relevant_blocks);
relevant_blocks = UniValue(UniValue::VARR);
}
BlockFiltersScanReserver reserver;
if (!reserver.reserve()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" or \"status\"");
@ -2669,7 +2690,7 @@ static RPCHelpMan scanblocks()
needle_set.emplace(script.begin(), script.end());
}
}
UniValue blocks(UniValue::VARR);
const int amount_per_chunk = 10000;
std::vector<BlockFilter> filters;
int start_block_height = start_index->nHeight; // for progress reporting
@ -2707,7 +2728,8 @@ static RPCHelpMan scanblocks()
}
}
blocks.push_back(filter.GetBlockHash().GetHex());
LOCK(cs_relevant_blocks);
relevant_blocks.push_back(filter.GetBlockHash().GetHex());
}
}
}
@ -2727,8 +2749,10 @@ static RPCHelpMan scanblocks()
ret.pushKV("from_height", start_block_height);
ret.pushKV("to_height", start_index->nHeight); // start_index is always the last scanned block here
ret.pushKV("relevant_blocks", std::move(blocks));
LOCK(cs_relevant_blocks);
ret.pushKV("relevant_blocks", std::move(relevant_blocks));
ret.pushKV("completed", completed);
reserver.release(); // ensure this is before cs_relevant_blocks is released, so status doesn't try to use moved relevant_blocks
}
else {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid action '%s'", request.params[0].get_str()));