@@ -130,19 +130,30 @@ std::optional<std::pair<uint256, int>> ChainScanner::ReadNextBlock(ScanResult& r
130130 return std::make_pair (block_hash, block_height);
131131}
132132
133- bool ChainScanner::ShouldFetchBlock (const std::unique_ptr<FastWalletRescanFilter>& filter, const uint256& block_hash, int block_height) {
133+ std::optional<std::pair<size_t , size_t >> ChainScanner::ReadNextBlocks (const std::unique_ptr<FastWalletRescanFilter>& filter, ScanResult& result) {
134+ auto next_block = ReadNextBlock (result);
135+ if (next_block) m_blocks.emplace_back (*next_block);
136+ else return std::nullopt ;
137+
138+ if (!filter) {
139+ // Slow scan: scan all blocks.
140+ return std::make_pair<size_t , size_t >(0 , 1 );
141+ }
142+
143+ filter->UpdateIfNeeded ();
144+
145+ const auto & [block_hash, block_height] = m_blocks[0 ];
134146 auto matches_block{filter->MatchesBlock (block_hash)};
135- if (matches_block.has_value ()) {
136- if (*matches_block) {
137- LogDebug (BCLog::SCAN, " Fast rescan: inspect block %d [%s] (filter matched)\n " , block_height, block_hash.ToString ());
138- return true ;
139- } else {
140- return false ;
141- }
142- } else {
147+
148+ if (matches_block.has_value () && *matches_block) {
149+ LogDebug (BCLog::SCAN, " Fast rescan: inspect block %d [%s] (filter matched)\n " , block_height, block_hash.ToString ());
150+ return std::make_pair<size_t , size_t >(0 , 1 );
151+ } else if (!matches_block.has_value ()) {
143152 LogDebug (BCLog::SCAN, " Fast rescan: inspect block %d [%s] (WARNING: block filter not found!)\n " , block_height, block_hash.ToString ());
144- return true ;
153+ return std::make_pair< size_t , size_t >( 0 , 1 ) ;
145154 }
155+
156+ return std::nullopt ;
146157}
147158
148159void ChainScanner::UpdateProgress (int block_height) {
@@ -166,18 +177,13 @@ void ChainScanner::UpdateTipIfChanged() {
166177 }
167178}
168179
169- void ChainScanner::ProcessBlock (const uint256& block_hash, int block_height, bool fetch_block, bool next_interval, ScanResult& result) {
170- if (fetch_block) {
171- if (ScanBlock (block_hash, block_height, m_save_progress && next_interval)) {
172- result.last_scanned_block = block_hash;
173- result.last_scanned_height = block_height;
174- } else {
175- result.last_failed_block = block_hash;
176- result.status = ScanResult::FAILURE;
177- }
178- } else {
180+ void ChainScanner::ProcessBlock (const uint256& block_hash, int block_height, bool next_interval, ScanResult& result) {
181+ if (ScanBlock (block_hash, block_height, m_save_progress && next_interval)) {
179182 result.last_scanned_block = block_hash;
180183 result.last_scanned_height = block_height;
184+ } else {
185+ result.last_failed_block = block_hash;
186+ result.status = ScanResult::FAILURE;
181187 }
182188}
183189
@@ -239,26 +245,40 @@ ScanResult ChainScanner::Scan() {
239245 int block_height = m_start_height;
240246 m_next_block = {{m_start_block, m_start_height}};
241247
242- while (!m_wallet.fAbortRescan && !chain.shutdownRequested ()) {
243- auto current_block = ReadNextBlock (result);
244- if (!current_block) break ;
245-
246- const auto & [block_hash, block_height] = *current_block;
248+ while ((m_next_block || !m_blocks.empty ()) && !m_wallet.fAbortRescan && !chain.shutdownRequested ()) {
249+ uint256 block_hash;
250+ auto range = ReadNextBlocks (fast_rescan_filter, result);
251+
252+ // If no blocks to scan, mark current batch as scanned
253+ size_t start_index = range.has_value () ? range->first : m_blocks.size ();
254+ size_t end_index = range.has_value () ? range->second : m_blocks.size ();
255+ if (start_index > 0 ) {
256+ // Some blocks at the start of the batch were skipped.
257+ // Update last scanned block to indicate that these
258+ // blocks have been scanned.
259+ block_hash = m_blocks[start_index - 1 ].first ;
260+ block_height = m_blocks[start_index - 1 ].second ;
261+ result.last_scanned_block = block_hash;
262+ result.last_scanned_height = block_height;
263+ }
247264
248- UpdateProgress (block_height);
265+ for (size_t i = start_index; i < end_index; ++i) {
266+ block_hash = m_blocks[i].first ;
267+ block_height = m_blocks[i].second ;
249268
250- bool next_interval = m_reserver.now () >= current_time + INTERVAL_TIME;
251- if (next_interval) {
252- current_time = m_reserver.now ();
253- m_wallet.WalletLogPrintf (" Still rescanning. At block %d. Progress=%f\n " , block_height, m_progress_current);
254- }
269+ UpdateProgress (block_height);
255270
256- bool fetch_block = !fast_rescan_filter ||
257- (fast_rescan_filter->UpdateIfNeeded (), ShouldFetchBlock (fast_rescan_filter, block_hash, block_height));
271+ bool next_interval = m_reserver.now () >= current_time + INTERVAL_TIME;
272+ if (next_interval) {
273+ current_time = m_reserver.now ();
274+ m_wallet.WalletLogPrintf (" Still rescanning. At block %d. Progress=%f\n " , block_height, m_progress_current);
275+ }
258276
259- ProcessBlock (block_hash, block_height, fetch_block, next_interval, result);
260- m_progress_current = chain.guessVerificationProgress (block_hash);
261- if (!m_max_height) UpdateTipIfChanged ();
277+ ProcessBlock (block_hash, block_height, next_interval, result);
278+ m_progress_current = chain.guessVerificationProgress (block_hash);
279+ if (!m_max_height) UpdateTipIfChanged ();
280+ }
281+ m_blocks.erase (m_blocks.begin (), m_blocks.begin () + end_index);
262282 }
263283 if (!m_max_height) {
264284 m_wallet.WalletLogPrintf (" Scanning current mempool transactions.\n " );
0 commit comments