Skip to content

Commit 4c9dc4b

Browse files
tdb3luke-jr
andcommitted
rpc: add relevant_blocks to scanblocks status
Provides relevant block hashes to status output. Enables a user to start looking through matching blocks without having to wait on scan completion. Co-Authored-By: Luke Dashjr <[email protected]>
1 parent 94bc3c4 commit 4c9dc4b

File tree

1 file changed

+28
-4
lines changed

1 file changed

+28
-4
lines changed

src/rpc/blockchain.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2365,9 +2365,17 @@ class BlockFiltersScanReserver
23652365
return true;
23662366
}
23672367

2368+
void release() {
2369+
if (!m_could_reserve) {
2370+
throw std::runtime_error("Attempt to release unreserved BlockFiltersScanReserver");
2371+
}
2372+
g_scanfilter_in_progress = false;
2373+
m_could_reserve = false;
2374+
}
2375+
23682376
~BlockFiltersScanReserver() {
23692377
if (m_could_reserve) {
2370-
g_scanfilter_in_progress = false;
2378+
release();
23712379
}
23722380
}
23732381
};
@@ -2427,6 +2435,9 @@ static RPCHelpMan scanblocks()
24272435
RPCResult{"when action=='status' and a scan is currently in progress", RPCResult::Type::OBJ, "", "", {
24282436
{RPCResult::Type::NUM, "progress", "Approximate percent complete"},
24292437
{RPCResult::Type::NUM, "current_height", "Height of the block currently being scanned"},
2438+
{RPCResult::Type::ARR, "relevant_blocks", "Blocks that may have matched a scanobject.", {
2439+
{RPCResult::Type::STR_HEX, "blockhash", "A relevant blockhash"},
2440+
}},
24302441
},
24312442
},
24322443
scan_result_abort,
@@ -2441,15 +2452,20 @@ static RPCHelpMan scanblocks()
24412452
},
24422453
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
24432454
{
2455+
static GlobalMutex cs_relevant_blocks;
2456+
static UniValue relevant_blocks GUARDED_BY(cs_relevant_blocks);
2457+
24442458
UniValue ret(UniValue::VOBJ);
24452459
if (request.params[0].get_str() == "status") {
24462460
BlockFiltersScanReserver reserver;
2461+
LOCK(cs_relevant_blocks);
24472462
if (reserver.reserve()) {
24482463
// no scan in progress
24492464
return NullUniValue;
24502465
}
24512466
ret.pushKV("progress", g_scanfilter_progress.load());
24522467
ret.pushKV("current_height", g_scanfilter_progress_height.load());
2468+
ret.pushKV("relevant_blocks", relevant_blocks);
24532469
return ret;
24542470
} else if (request.params[0].get_str() == "abort") {
24552471
BlockFiltersScanReserver reserver;
@@ -2461,6 +2477,11 @@ static RPCHelpMan scanblocks()
24612477
g_scanfilter_should_abort_scan = true;
24622478
return true;
24632479
} else if (request.params[0].get_str() == "start") {
2480+
{
2481+
LOCK(cs_relevant_blocks);
2482+
relevant_blocks = UniValue(UniValue::VARR);
2483+
}
2484+
24642485
BlockFiltersScanReserver reserver;
24652486
if (!reserver.reserve()) {
24662487
throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" or \"status\"");
@@ -2516,7 +2537,7 @@ static RPCHelpMan scanblocks()
25162537
needle_set.emplace(script.begin(), script.end());
25172538
}
25182539
}
2519-
UniValue blocks(UniValue::VARR);
2540+
25202541
const int amount_per_chunk = 10000;
25212542
std::vector<BlockFilter> filters;
25222543
int start_block_height = start_index->nHeight; // for progress reporting
@@ -2554,7 +2575,8 @@ static RPCHelpMan scanblocks()
25542575
}
25552576
}
25562577

2557-
blocks.push_back(filter.GetBlockHash().GetHex());
2578+
LOCK(cs_relevant_blocks);
2579+
relevant_blocks.push_back(filter.GetBlockHash().GetHex());
25582580
}
25592581
}
25602582
}
@@ -2574,8 +2596,10 @@ static RPCHelpMan scanblocks()
25742596

25752597
ret.pushKV("from_height", start_block_height);
25762598
ret.pushKV("to_height", start_index->nHeight); // start_index is always the last scanned block here
2577-
ret.pushKV("relevant_blocks", std::move(blocks));
2599+
LOCK(cs_relevant_blocks);
2600+
ret.pushKV("relevant_blocks", std::move(relevant_blocks));
25782601
ret.pushKV("completed", completed);
2602+
reserver.release(); // ensure this is before cs_relevant_blocks is released, so status doesn't try to use moved relevant_blocks
25792603
}
25802604
else {
25812605
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid action '%s'", request.params[0].get_str()));

0 commit comments

Comments
 (0)