@@ -41,59 +41,40 @@ impl<'a> FilterIter<'a> {
4141 }
4242 }
4343
44- /// Find the agreement height with the remote node and return the corresponding
45- /// header info.
44+ /// Return the agreement header with the remote node.
4645 ///
47- /// Error if no agreement height is found.
46+ /// Error if no agreement header is found.
4847 fn find_base ( & self ) -> Result < GetBlockHeaderResult , Error > {
4948 for cp in self . cp . iter ( ) {
50- let height = cp. height ( ) ;
51-
52- let fetched_hash = self . client . get_block_hash ( height as u64 ) ?;
53-
54- if fetched_hash == cp. hash ( ) {
55- return Ok ( self . client . get_block_header_info ( & fetched_hash) ?) ;
49+ match self . client . get_block_header_info ( & cp. hash ( ) ) {
50+ Err ( e) if is_not_found ( & e) => continue ,
51+ Ok ( header) if header. confirmations <= 0 => continue ,
52+ Ok ( header) => return Ok ( header) ,
53+ Err ( e) => return Err ( Error :: Rpc ( e) ) ,
5654 }
5755 }
58-
5956 Err ( Error :: ReorgDepthExceeded )
6057 }
6158}
6259
63- /// Kind of event produced by `FilterIter`.
60+ /// Event returned by [ `FilterIter`] .
6461#[ derive( Debug , Clone ) ]
65- pub enum Event {
66- /// Block
67- Block {
68- /// checkpoint
69- cp : CheckPoint ,
70- /// block
71- block : Block ,
72- } ,
73- /// No match
74- NoMatch {
75- /// block id
76- id : BlockId ,
77- } ,
78- /// Tip
79- Tip {
80- /// checkpoint
81- cp : CheckPoint ,
82- } ,
62+ pub struct Event {
63+ /// Checkpoint
64+ pub cp : CheckPoint ,
65+ /// Block, will be `Some(..)` for matching blocks
66+ pub block : Option < Block > ,
8367}
8468
8569impl Event {
8670 /// Whether this event contains a matching block.
8771 pub fn is_match ( & self ) -> bool {
88- matches ! ( self , Event :: Block { .. } )
72+ self . block . is_some ( )
8973 }
9074
9175 /// Return the height of the event.
9276 pub fn height ( & self ) -> u32 {
93- match self {
94- Self :: Block { cp, .. } | Self :: Tip { cp } => cp. height ( ) ,
95- Self :: NoMatch { id } => id. height ,
96- }
77+ self . cp . height ( )
9778 }
9879}
9980
@@ -106,15 +87,9 @@ impl Iterator for FilterIter<'_> {
10687
10788 let header = match self . header . take ( ) {
10889 Some ( header) => header,
109- None => {
110- // If no header is cached we need to locate a base of the local
111- // checkpoint from which the scan may proceed.
112- let header = self . find_base ( ) ?;
113- let height: u32 = header. height . try_into ( ) ?;
114- cp = cp. range ( ..=height) . next ( ) . expect ( "we found a base" ) ;
115-
116- header
117- }
90+ // If no header is cached we need to locate a base of the local
91+ // checkpoint from which the scan may proceed.
92+ None => self . find_base ( ) ?,
11893 } ;
11994
12095 let mut next_hash = match header. next_block_hash {
@@ -126,58 +101,38 @@ impl Iterator for FilterIter<'_> {
126101
127102 // In case of a reorg, rewind by fetching headers of previous hashes until we find
128103 // one with enough confirmations.
129- let mut reorg_ct: i32 = 0 ;
130104 while next_header. confirmations < 0 {
131105 let prev_hash = next_header
132106 . previous_block_hash
133107 . ok_or ( Error :: ReorgDepthExceeded ) ?;
134108 let prev_header = self . client . get_block_header_info ( & prev_hash) ?;
135109 next_header = prev_header;
136- reorg_ct += 1 ;
137110 }
138111
139112 next_hash = next_header. hash ;
140113 let next_height: u32 = next_header. height . try_into ( ) ?;
141114
142- // Purge any no longer valid checkpoints.
143- if reorg_ct. is_positive ( ) {
144- cp = cp
145- . range ( ..=next_height)
146- . next ( )
147- . ok_or ( Error :: ReorgDepthExceeded ) ?;
148- }
149- let block_id = BlockId {
115+ cp = cp. insert ( BlockId {
150116 height : next_height,
151117 hash : next_hash,
152- } ;
153- let filter_bytes = self . client . get_block_filter ( & next_hash) ?. filter ;
154- let filter = BlockFilter :: new ( & filter_bytes) ;
118+ } ) ;
155119
156- let next_event = if filter
120+ let mut block = None ;
121+ let filter =
122+ BlockFilter :: new ( self . client . get_block_filter ( & next_hash) ?. filter . as_slice ( ) ) ;
123+ if filter
157124 . match_any ( & next_hash, self . spks . iter ( ) . map ( ScriptBuf :: as_ref) )
158125 . map_err ( Error :: Bip158 ) ?
159126 {
160- let block = self . client . get_block ( & next_hash) ?;
161- cp = cp. insert ( block_id) ;
162-
163- Ok ( Some ( Event :: Block {
164- cp : cp. clone ( ) ,
165- block,
166- } ) )
167- } else if next_header. next_block_hash . is_none ( ) {
168- cp = cp. insert ( block_id) ;
169-
170- Ok ( Some ( Event :: Tip { cp : cp. clone ( ) } ) )
171- } else {
172- Ok ( Some ( Event :: NoMatch { id : block_id } ) )
173- } ;
127+ block = Some ( self . client . get_block ( & next_hash) ?) ;
128+ }
174129
175130 // Store the next header
176131 self . header = Some ( next_header) ;
177132 // Update self.cp
178- self . cp = cp;
133+ self . cp = cp. clone ( ) ;
179134
180- next_event
135+ Ok ( Some ( Event { cp , block } ) )
181136 } ) ( )
182137 . transpose ( )
183138 }
@@ -221,3 +176,12 @@ impl From<core::num::TryFromIntError> for Error {
221176 Self :: TryFromInt ( e)
222177 }
223178}
179+
180+ /// Whether the RPC error is a "not found" error (code: `-5`).
181+ fn is_not_found ( e : & bitcoincore_rpc:: Error ) -> bool {
182+ matches ! (
183+ e,
184+ bitcoincore_rpc:: Error :: JsonRpc ( bitcoincore_rpc:: jsonrpc:: Error :: Rpc ( e) )
185+ if e. code == -5
186+ )
187+ }
0 commit comments