@@ -153,7 +153,7 @@ where
153153 }
154154 }
155155
156- match maybe_await ! ( self . sync_best_block_updated( & confirmables, & tip_hash) ) {
156+ match maybe_await ! ( self . sync_best_block_updated( & confirmables, & mut sync_state , & tip_hash) ) {
157157 Ok ( ( ) ) => { }
158158 Err ( InternalError :: Inconsistency ) => {
159159 // Immediately restart syncing when we encounter any inconsistencies.
@@ -238,7 +238,7 @@ where
238238
239239 #[ maybe_async]
240240 fn sync_best_block_updated (
241- & self , confirmables : & Vec < & ( dyn Confirm + Sync + Send ) > , tip_hash : & BlockHash ,
241+ & self , confirmables : & Vec < & ( dyn Confirm + Sync + Send ) > , sync_state : & mut SyncState , tip_hash : & BlockHash ,
242242 ) -> Result < ( ) , InternalError > {
243243
244244 // Inform the interface of the new block.
@@ -249,6 +249,9 @@ where
249249 for c in confirmables {
250250 c. best_block_updated ( & tip_header, tip_height) ;
251251 }
252+
253+ // Prune any sufficiently confirmed output spends
254+ sync_state. prune_output_spends ( tip_height) ;
252255 }
253256 } else {
254257 return Err ( InternalError :: Inconsistency ) ;
@@ -264,10 +267,13 @@ where
264267 // First, check the confirmation status of registered transactions as well as the
265268 // status of dependent transactions of registered outputs.
266269
267- let mut confirmed_txs = Vec :: new ( ) ;
270+ let mut confirmed_txs: Vec < ConfirmedTx > = Vec :: new ( ) ;
268271
269272 for txid in & sync_state. watched_transactions {
270- if let Some ( confirmed_tx) = maybe_await ! ( self . get_confirmed_tx( & txid, None , None ) ) ? {
273+ if confirmed_txs. iter ( ) . any ( |ctx| ctx. txid == * txid) {
274+ continue ;
275+ }
276+ if let Some ( confirmed_tx) = maybe_await ! ( self . get_confirmed_tx( * txid, None , None ) ) ? {
271277 confirmed_txs. push ( confirmed_tx) ;
272278 }
273279 }
@@ -278,9 +284,19 @@ where
278284 {
279285 if let Some ( spending_txid) = output_status. txid {
280286 if let Some ( spending_tx_status) = output_status. status {
287+ if confirmed_txs. iter ( ) . any ( |ctx| ctx. txid == spending_txid) {
288+ if spending_tx_status. confirmed {
289+ // Skip inserting duplicate ConfirmedTx entry
290+ continue ;
291+ } else {
292+ log_trace ! ( self . logger, "Inconsistency: Detected previously-confirmed Tx {} as unconfirmed" , spending_txid) ;
293+ return Err ( InternalError :: Inconsistency ) ;
294+ }
295+ }
296+
281297 if let Some ( confirmed_tx) = maybe_await ! ( self
282298 . get_confirmed_tx(
283- & spending_txid,
299+ spending_txid,
284300 spending_tx_status. block_hash,
285301 spending_tx_status. block_height,
286302 ) ) ?
@@ -303,7 +319,7 @@ where
303319
304320 #[ maybe_async]
305321 fn get_confirmed_tx (
306- & self , txid : & Txid , expected_block_hash : Option < BlockHash > , known_block_height : Option < u32 > ,
322+ & self , txid : Txid , expected_block_hash : Option < BlockHash > , known_block_height : Option < u32 > ,
307323 ) -> Result < Option < ConfirmedTx > , InternalError > {
308324 if let Some ( merkle_block) = maybe_await ! ( self . client. get_merkle_block( & txid) ) ? {
309325 let block_header = merkle_block. header ;
@@ -318,22 +334,27 @@ where
318334 let mut matches = Vec :: new ( ) ;
319335 let mut indexes = Vec :: new ( ) ;
320336 let _ = merkle_block. txn . extract_matches ( & mut matches, & mut indexes) ;
321- if indexes. len ( ) != 1 || matches. len ( ) != 1 || matches[ 0 ] != * txid {
337+ if indexes. len ( ) != 1 || matches. len ( ) != 1 || matches[ 0 ] != txid {
322338 log_error ! ( self . logger, "Retrieved Merkle block for txid {} doesn't match expectations. This should not happen. Please verify server integrity." , txid) ;
323339 return Err ( InternalError :: Failed ) ;
324340 }
325341
326342 // unwrap() safety: len() > 0 is checked above
327343 let pos = * indexes. first ( ) . unwrap ( ) as usize ;
328344 if let Some ( tx) = maybe_await ! ( self . client. get_tx( & txid) ) ? {
345+ if tx. txid ( ) != txid {
346+ log_error ! ( self . logger, "Retrieved transaction for txid {} doesn't match expectations. This should not happen. Please verify server integrity." , txid) ;
347+ return Err ( InternalError :: Failed ) ;
348+ }
349+
329350 if let Some ( block_height) = known_block_height {
330351 // We can take a shortcut here if a previous call already gave us the height.
331- return Ok ( Some ( ConfirmedTx { tx, block_header, pos, block_height } ) ) ;
352+ return Ok ( Some ( ConfirmedTx { tx, txid , block_header, pos, block_height } ) ) ;
332353 }
333354
334355 let block_status = maybe_await ! ( self . client. get_block_status( & block_hash) ) ?;
335356 if let Some ( block_height) = block_status. height {
336- return Ok ( Some ( ConfirmedTx { tx, block_header, pos, block_height } ) ) ;
357+ return Ok ( Some ( ConfirmedTx { tx, txid , block_header, pos, block_height } ) ) ;
337358 } else {
338359 // If any previously-confirmed block suddenly is no longer confirmed, we found
339360 // an inconsistency and should start over.
0 commit comments