@@ -178,10 +178,12 @@ impl<C: RpcApi> Iterator for FilterIter<'_, C> {
178178 let height = block. height ;
179179 let hash = block. hash ;
180180
181- // Check continuity with previous block
182- if height > 0 {
181+ // Check continuity with previous block for recent blocks
182+ // Only check blocks within the last 100 blocks as deep reorgs are extremely rare
183+ if height > 0 && height > self . height . saturating_sub ( 100 ) {
183184 let prev_height = height - 1 ;
184185
186+ // Use cached block if available, otherwise fetch
185187 let prev_hash = match self . blocks . get ( & prev_height) . copied ( ) {
186188 Some ( hash) => hash,
187189 None => self . client . get_block_hash ( prev_height as u64 ) ?,
@@ -204,16 +206,14 @@ impl<C: RpcApi> Iterator for FilterIter<'_, C> {
204206
205207 if self . spks . is_empty ( ) {
206208 return Err ( Error :: NoScripts ) ;
207- }
208-
209- let matches = filter
210- . match_any ( & hash, self . spks . iter ( ) . map ( |s| s. as_bytes ( ) ) )
211- . map_err ( Error :: Bip158 ) ?;
212-
213- if matches {
209+ } else if filter
210+ . match_any ( & hash, self . spks . iter ( ) . map ( |script| script. as_bytes ( ) ) )
211+ . map_err ( Error :: Bip158 ) ?
212+ {
214213 let block = self . client . get_block ( & hash) ?;
215214 self . blocks . insert ( height, hash) ;
216- return Ok ( Some ( Event :: Block ( EventInner { height, block } ) ) ) ;
215+ let inner = EventInner { height, block } ;
216+ return Ok ( Some ( Event :: Block ( inner) ) ) ;
217217 } else {
218218 return Ok ( Some ( Event :: NoMatch ( height) ) ) ;
219219 }
@@ -247,24 +247,61 @@ impl<C: RpcApi> FilterIter<'_, C> {
247247 }
248248 }
249249
250- /// Find the fork point by checking previous blocks
251- fn find_fork_point ( & self , mut height : u32 ) -> Result < u32 , Error > {
252- let lookback_depth = 10 ; // Adjust based on security needs
253- let min_height = height. saturating_sub ( lookback_depth) ;
250+ fn find_fork_point ( & self , current_height : u32 ) -> Result < u32 , Error > {
251+ // Try a quick check of the immediate previous block first (common case)
252+ if current_height > 0 {
253+ let prev_height = current_height - 1 ;
254+ let prev_hash = self . client . get_block_hash ( prev_height as u64 ) ?;
255+ let prev_header = self . client . get_block_header_info ( & prev_hash) ?;
256+
257+ // If previous block links properly to its parent, it's valid
258+ if prev_height == 0
259+ || prev_header. previous_block_hash . is_some ( )
260+ && prev_header. previous_block_hash
261+ == Some ( self . client . get_block_hash ( ( prev_height - 1 ) as u64 ) ?)
262+ {
263+ return Ok ( prev_height) ;
264+ }
265+ }
254266
255- while height > min_height {
256- height -= 1 ;
257- let current_hash = self . client . get_block_hash ( height as u64 ) ?;
258- let current_header = self . client . get_block_header_info ( & current_hash) ?;
267+ // Binary search for fork point
268+ let max_lookback = 10 ; // Adjust based on security needs
269+ let min_height = current_height. saturating_sub ( max_lookback) ;
259270
260- if height == 0
261- || current_header. previous_block_hash
262- == Some ( self . client . get_block_hash ( ( height - 1 ) as u64 ) ?)
263- {
264- return Ok ( height) ;
271+ let mut low = min_height;
272+ let mut high = current_height. saturating_sub ( 1 ) ;
273+
274+ while low <= high {
275+ let mid = low + ( high - low) / 2 ;
276+
277+ // Check if this block is valid in the chain
278+ let hash = self . client . get_block_hash ( mid as u64 ) ?;
279+ let header = self . client . get_block_header_info ( & hash) ?;
280+
281+ let is_valid = if mid == 0 {
282+ true // Genesis is always valid
283+ } else {
284+ let prev_hash = self . client . get_block_hash ( ( mid - 1 ) as u64 ) ?;
285+ header. previous_block_hash == Some ( prev_hash)
286+ } ;
287+
288+ if is_valid {
289+ // Check if the next block is invalid, which would make this our fork point
290+ if mid == high || {
291+ let next_hash = self . client . get_block_hash ( ( mid + 1 ) as u64 ) ?;
292+ let next_header = self . client . get_block_header_info ( & next_hash) ?;
293+ next_header. previous_block_hash != Some ( hash)
294+ } {
295+ return Ok ( mid) ;
296+ }
297+ low = mid + 1 ;
298+ } else {
299+ high = mid - 1 ;
265300 }
266301 }
267- Ok ( 0 ) // Fallback to genesis
302+
303+ // Fall back to lowest valid block or genesis
304+ Ok ( low. saturating_sub ( 1 ) )
268305 }
269306
270307 /// Returns a chain update from the newly scanned blocks.
0 commit comments