@@ -153,7 +153,7 @@ where
153
153
}
154
154
}
155
155
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) ) {
157
157
Ok ( ( ) ) => { }
158
158
Err ( InternalError :: Inconsistency ) => {
159
159
// Immediately restart syncing when we encounter any inconsistencies.
@@ -238,7 +238,7 @@ where
238
238
239
239
#[ maybe_async]
240
240
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 ,
242
242
) -> Result < ( ) , InternalError > {
243
243
244
244
// Inform the interface of the new block.
@@ -249,6 +249,9 @@ where
249
249
for c in confirmables {
250
250
c. best_block_updated ( & tip_header, tip_height) ;
251
251
}
252
+
253
+ // Prune any sufficiently confirmed output spends
254
+ sync_state. prune_output_spends ( tip_height) ;
252
255
}
253
256
} else {
254
257
return Err ( InternalError :: Inconsistency ) ;
@@ -264,10 +267,13 @@ where
264
267
// First, check the confirmation status of registered transactions as well as the
265
268
// status of dependent transactions of registered outputs.
266
269
267
- let mut confirmed_txs = Vec :: new ( ) ;
270
+ let mut confirmed_txs: Vec < ConfirmedTx > = Vec :: new ( ) ;
268
271
269
272
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 ) ) ? {
271
277
confirmed_txs. push ( confirmed_tx) ;
272
278
}
273
279
}
@@ -278,9 +284,19 @@ where
278
284
{
279
285
if let Some ( spending_txid) = output_status. txid {
280
286
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
+
281
297
if let Some ( confirmed_tx) = maybe_await ! ( self
282
298
. get_confirmed_tx(
283
- & spending_txid,
299
+ spending_txid,
284
300
spending_tx_status. block_hash,
285
301
spending_tx_status. block_height,
286
302
) ) ?
@@ -303,7 +319,7 @@ where
303
319
304
320
#[ maybe_async]
305
321
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 > ,
307
323
) -> Result < Option < ConfirmedTx > , InternalError > {
308
324
if let Some ( merkle_block) = maybe_await ! ( self . client. get_merkle_block( & txid) ) ? {
309
325
let block_header = merkle_block. header ;
@@ -318,22 +334,27 @@ where
318
334
let mut matches = Vec :: new ( ) ;
319
335
let mut indexes = Vec :: new ( ) ;
320
336
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 {
322
338
log_error ! ( self . logger, "Retrieved Merkle block for txid {} doesn't match expectations. This should not happen. Please verify server integrity." , txid) ;
323
339
return Err ( InternalError :: Failed ) ;
324
340
}
325
341
326
342
// unwrap() safety: len() > 0 is checked above
327
343
let pos = * indexes. first ( ) . unwrap ( ) as usize ;
328
344
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
+
329
350
if let Some ( block_height) = known_block_height {
330
351
// 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 } ) ) ;
332
353
}
333
354
334
355
let block_status = maybe_await ! ( self . client. get_block_status( & block_hash) ) ?;
335
356
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 } ) ) ;
337
358
} else {
338
359
// If any previously-confirmed block suddenly is no longer confirmed, we found
339
360
// an inconsistency and should start over.
0 commit comments