@@ -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