@@ -2383,27 +2383,28 @@ static RPCHelpMan scanblocks()
2383
2383
ChainstateManager& chainman = EnsureChainman (node);
2384
2384
2385
2385
// set the start-height
2386
- const CBlockIndex* block = nullptr ;
2386
+ const CBlockIndex* start_index = nullptr ;
2387
2387
const CBlockIndex* stop_block = nullptr ;
2388
2388
{
2389
2389
LOCK (cs_main);
2390
2390
CChain& active_chain = chainman.ActiveChain ();
2391
- block = active_chain.Genesis ();
2392
- stop_block = active_chain.Tip ();
2391
+ start_index = active_chain.Genesis ();
2392
+ stop_block = active_chain.Tip (); // If no stop block is provided, stop at the chain tip.
2393
2393
if (!request.params [2 ].isNull ()) {
2394
- block = active_chain[request.params [2 ].getInt <int >()];
2395
- if (!block ) {
2394
+ start_index = active_chain[request.params [2 ].getInt <int >()];
2395
+ if (!start_index ) {
2396
2396
throw JSONRPCError (RPC_MISC_ERROR, " Invalid start_height" );
2397
2397
}
2398
2398
}
2399
2399
if (!request.params [3 ].isNull ()) {
2400
2400
stop_block = active_chain[request.params [3 ].getInt <int >()];
2401
- if (!stop_block || stop_block->nHeight < block ->nHeight ) {
2401
+ if (!stop_block || stop_block->nHeight < start_index ->nHeight ) {
2402
2402
throw JSONRPCError (RPC_MISC_ERROR, " Invalid stop_height" );
2403
2403
}
2404
2404
}
2405
2405
}
2406
- CHECK_NONFATAL (block);
2406
+ CHECK_NONFATAL (start_index);
2407
+ CHECK_NONFATAL (stop_block);
2407
2408
2408
2409
// loop through the scan objects, add scripts to the needle_set
2409
2410
GCSFilter::ElementSet needle_set;
@@ -2416,63 +2417,62 @@ static RPCHelpMan scanblocks()
2416
2417
}
2417
2418
UniValue blocks (UniValue::VARR);
2418
2419
const int amount_per_chunk = 10000 ;
2419
- const CBlockIndex* start_index = block; // for remembering the start of a blockfilter range
2420
2420
std::vector<BlockFilter> filters;
2421
- const CBlockIndex* start_block = block ; // for progress reporting
2422
- const int total_blocks_to_process = stop_block->nHeight - start_block-> nHeight ;
2421
+ int start_block_height = start_index-> nHeight ; // for progress reporting
2422
+ const int total_blocks_to_process = stop_block->nHeight - start_block_height ;
2423
2423
2424
2424
g_scanfilter_should_abort_scan = false ;
2425
2425
g_scanfilter_progress = 0 ;
2426
- g_scanfilter_progress_height = start_block-> nHeight ;
2426
+ g_scanfilter_progress_height = start_block_height ;
2427
2427
2428
- while (block) {
2428
+ const CBlockIndex* end_range = nullptr ;
2429
+ do {
2429
2430
node.rpc_interruption_point (); // allow a clean shutdown
2430
2431
if (g_scanfilter_should_abort_scan) {
2431
- LogPrintf (" scanblocks RPC aborted at height %d.\n " , block ->nHeight );
2432
+ LogPrintf (" scanblocks RPC aborted at height %d.\n " , end_range ->nHeight );
2432
2433
break ;
2433
2434
}
2434
- const CBlockIndex* next = nullptr ;
2435
- {
2436
- LOCK (cs_main);
2437
- CChain& active_chain = chainman.ActiveChain ();
2438
- next = active_chain.Next (block);
2439
- if (block == stop_block) next = nullptr ;
2440
- }
2441
- if (start_index->nHeight + amount_per_chunk == block->nHeight || next == nullptr ) {
2442
- LogPrint (BCLog::RPC, " Fetching blockfilters from height %d to height %d.\n " , start_index->nHeight , block->nHeight );
2443
- if (index->LookupFilterRange (start_index->nHeight , block, filters)) {
2444
- for (const BlockFilter& filter : filters) {
2445
- // compare the elements-set with each filter
2446
- if (filter.GetFilter ().MatchAny (needle_set)) {
2447
- if (filter_false_positives) {
2448
- // Double check the filter matches by scanning the block
2449
- const CBlockIndex& blockindex = *CHECK_NONFATAL (WITH_LOCK (cs_main, return chainman.m_blockman .LookupBlockIndex (filter.GetBlockHash ())));
2450
-
2451
- if (!CheckBlockFilterMatches (chainman.m_blockman , blockindex, needle_set)) {
2452
- continue ;
2453
- }
2454
- }
2455
2435
2456
- blocks.push_back (filter.GetBlockHash ().GetHex ());
2457
- LogPrint (BCLog::RPC, " scanblocks: found match in %s\n " , filter.GetBlockHash ().GetHex ());
2436
+ // split the lookup range in chunks if we are deeper than 'amount_per_chunk' blocks from the stopping block
2437
+ int start_block = !end_range ? start_index->nHeight : start_index->nHeight + 1 ; // to not include the previous round 'end_range' block
2438
+ end_range = (start_block + amount_per_chunk < stop_block->nHeight ) ?
2439
+ WITH_LOCK (::cs_main, return chainman.ActiveChain ()[start_block + amount_per_chunk]) :
2440
+ stop_block;
2441
+
2442
+ if (index->LookupFilterRange (start_block, end_range, filters)) {
2443
+ for (const BlockFilter& filter : filters) {
2444
+ // compare the elements-set with each filter
2445
+ if (filter.GetFilter ().MatchAny (needle_set)) {
2446
+ if (filter_false_positives) {
2447
+ // Double check the filter matches by scanning the block
2448
+ const CBlockIndex& blockindex = *CHECK_NONFATAL (WITH_LOCK (cs_main, return chainman.m_blockman .LookupBlockIndex (filter.GetBlockHash ())));
2449
+
2450
+ if (!CheckBlockFilterMatches (chainman.m_blockman , blockindex, needle_set)) {
2451
+ continue ;
2452
+ }
2458
2453
}
2454
+
2455
+ blocks.push_back (filter.GetBlockHash ().GetHex ());
2456
+ LogPrint (BCLog::RPC, " scanblocks: found match in %s\n " , filter.GetBlockHash ().GetHex ());
2459
2457
}
2460
2458
}
2461
- start_index = block;
2462
-
2463
- // update progress
2464
- int blocks_processed = block->nHeight - start_block->nHeight ;
2465
- if (total_blocks_to_process > 0 ) { // avoid division by zero
2466
- g_scanfilter_progress = (int )(100.0 / total_blocks_to_process * blocks_processed);
2467
- } else {
2468
- g_scanfilter_progress = 100 ;
2469
- }
2470
- g_scanfilter_progress_height = block->nHeight ;
2471
2459
}
2472
- block = next;
2473
- }
2474
- ret.pushKV (" from_height" , start_block->nHeight );
2475
- ret.pushKV (" to_height" , g_scanfilter_progress_height.load ());
2460
+ start_index = end_range;
2461
+
2462
+ // update progress
2463
+ int blocks_processed = end_range->nHeight - start_block_height;
2464
+ if (total_blocks_to_process > 0 ) { // avoid division by zero
2465
+ g_scanfilter_progress = (int )(100.0 / total_blocks_to_process * blocks_processed);
2466
+ } else {
2467
+ g_scanfilter_progress = 100 ;
2468
+ }
2469
+ g_scanfilter_progress_height = end_range->nHeight ;
2470
+
2471
+ // Finish if we reached the stop block
2472
+ } while (start_index != stop_block);
2473
+
2474
+ ret.pushKV (" from_height" , start_block_height);
2475
+ ret.pushKV (" to_height" , stop_block->nHeight );
2476
2476
ret.pushKV (" relevant_blocks" , blocks);
2477
2477
}
2478
2478
else {
0 commit comments