@@ -267,10 +267,13 @@ where
267
267
// First, check the confirmation status of registered transactions as well as the
268
268
// status of dependent transactions of registered outputs.
269
269
270
- let mut confirmed_txs = Vec :: new ( ) ;
270
+ let mut confirmed_txs: Vec < ConfirmedTx > = Vec :: new ( ) ;
271
271
272
272
for txid in & sync_state. watched_transactions {
273
- 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 ) ) ? {
274
277
confirmed_txs. push ( confirmed_tx) ;
275
278
}
276
279
}
@@ -281,9 +284,19 @@ where
281
284
{
282
285
if let Some ( spending_txid) = output_status. txid {
283
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
+
284
297
if let Some ( confirmed_tx) = maybe_await ! ( self
285
298
. get_confirmed_tx(
286
- & spending_txid,
299
+ spending_txid,
287
300
spending_tx_status. block_hash,
288
301
spending_tx_status. block_height,
289
302
) ) ?
@@ -306,7 +319,7 @@ where
306
319
307
320
#[ maybe_async]
308
321
fn get_confirmed_tx (
309
- & 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 > ,
310
323
) -> Result < Option < ConfirmedTx > , InternalError > {
311
324
if let Some ( merkle_block) = maybe_await ! ( self . client. get_merkle_block( & txid) ) ? {
312
325
let block_header = merkle_block. header ;
@@ -321,22 +334,27 @@ where
321
334
let mut matches = Vec :: new ( ) ;
322
335
let mut indexes = Vec :: new ( ) ;
323
336
let _ = merkle_block. txn . extract_matches ( & mut matches, & mut indexes) ;
324
- if indexes. len ( ) != 1 || matches. len ( ) != 1 || matches[ 0 ] != * txid {
337
+ if indexes. len ( ) != 1 || matches. len ( ) != 1 || matches[ 0 ] != txid {
325
338
log_error ! ( self . logger, "Retrieved Merkle block for txid {} doesn't match expectations. This should not happen. Please verify server integrity." , txid) ;
326
339
return Err ( InternalError :: Failed ) ;
327
340
}
328
341
329
342
// unwrap() safety: len() > 0 is checked above
330
343
let pos = * indexes. first ( ) . unwrap ( ) as usize ;
331
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
+
332
350
if let Some ( block_height) = known_block_height {
333
351
// We can take a shortcut here if a previous call already gave us the height.
334
- return Ok ( Some ( ConfirmedTx { tx, block_header, pos, block_height } ) ) ;
352
+ return Ok ( Some ( ConfirmedTx { tx, txid , block_header, pos, block_height } ) ) ;
335
353
}
336
354
337
355
let block_status = maybe_await ! ( self . client. get_block_status( & block_hash) ) ?;
338
356
if let Some ( block_height) = block_status. height {
339
- return Ok ( Some ( ConfirmedTx { tx, block_header, pos, block_height } ) ) ;
357
+ return Ok ( Some ( ConfirmedTx { tx, txid , block_header, pos, block_height } ) ) ;
340
358
} else {
341
359
// If any previously-confirmed block suddenly is no longer confirmed, we found
342
360
// an inconsistency and should start over.
0 commit comments