Skip to content

Commit b71c6e2

Browse files
committed
Dedup confirmed_txs Vec
Previously, we would just push to the `confirmed_txs` `Vec`, leading to redundant `Confirm::transactions_confirmed` calls, especially now that we re-confirm previously disconnected spends. Here, we ensure that we don't push additional `ConfirmedTx` entries if already one with matching `Txid` is present. This not only gets rid of the spurious `transactions_confirmed` calls (which are harmless), but more importantly saves us from issuing unnecessary network calls, which improves latency.
1 parent 2f58110 commit b71c6e2

File tree

3 files changed

+35
-8
lines changed

3 files changed

+35
-8
lines changed

lightning-transaction-sync/src/common.rs

+1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ impl FilterQueue {
128128
#[derive(Debug)]
129129
pub(crate) struct ConfirmedTx {
130130
pub tx: Transaction,
131+
pub txid: Txid,
131132
pub block_header: Header,
132133
pub block_height: u32,
133134
pub pos: usize,

lightning-transaction-sync/src/electrum.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ where
257257

258258
// First, check the confirmation status of registered transactions as well as the
259259
// status of dependent transactions of registered outputs.
260-
let mut confirmed_txs = Vec::new();
260+
let mut confirmed_txs: Vec<ConfirmedTx> = Vec::new();
261261
let mut watched_script_pubkeys = Vec::with_capacity(
262262
sync_state.watched_transactions.len() + sync_state.watched_outputs.len());
263263
let mut watched_txs = Vec::with_capacity(sync_state.watched_transactions.len());
@@ -305,6 +305,9 @@ where
305305

306306
for (i, script_history) in tx_results.iter().enumerate() {
307307
let (txid, tx) = &watched_txs[i];
308+
if confirmed_txs.iter().any(|ctx| ctx.txid == **txid) {
309+
continue;
310+
}
308311
let mut filtered_history = script_history.iter().filter(|h| h.tx_hash == **txid);
309312
if let Some(history) = filtered_history.next()
310313
{
@@ -324,6 +327,10 @@ where
324327
}
325328

326329
let txid = possible_output_spend.tx_hash;
330+
if confirmed_txs.iter().any(|ctx| ctx.txid == txid) {
331+
continue;
332+
}
333+
327334
match self.client.transaction_get(&txid) {
328335
Ok(tx) => {
329336
let mut is_spend = false;
@@ -419,6 +426,7 @@ where
419426
}
420427
let confirmed_tx = ConfirmedTx {
421428
tx: tx.clone(),
429+
txid,
422430
block_header, block_height: prob_conf_height,
423431
pos,
424432
};

lightning-transaction-sync/src/esplora.rs

+25-7
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,13 @@ where
267267
// First, check the confirmation status of registered transactions as well as the
268268
// status of dependent transactions of registered outputs.
269269

270-
let mut confirmed_txs = Vec::new();
270+
let mut confirmed_txs: Vec<ConfirmedTx> = Vec::new();
271271

272272
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))? {
274277
confirmed_txs.push(confirmed_tx);
275278
}
276279
}
@@ -281,9 +284,19 @@ where
281284
{
282285
if let Some(spending_txid) = output_status.txid {
283286
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+
284297
if let Some(confirmed_tx) = maybe_await!(self
285298
.get_confirmed_tx(
286-
&spending_txid,
299+
spending_txid,
287300
spending_tx_status.block_hash,
288301
spending_tx_status.block_height,
289302
))?
@@ -306,7 +319,7 @@ where
306319

307320
#[maybe_async]
308321
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>,
310323
) -> Result<Option<ConfirmedTx>, InternalError> {
311324
if let Some(merkle_block) = maybe_await!(self.client.get_merkle_block(&txid))? {
312325
let block_header = merkle_block.header;
@@ -321,22 +334,27 @@ where
321334
let mut matches = Vec::new();
322335
let mut indexes = Vec::new();
323336
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 {
325338
log_error!(self.logger, "Retrieved Merkle block for txid {} doesn't match expectations. This should not happen. Please verify server integrity.", txid);
326339
return Err(InternalError::Failed);
327340
}
328341

329342
// unwrap() safety: len() > 0 is checked above
330343
let pos = *indexes.first().unwrap() as usize;
331344
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+
332350
if let Some(block_height) = known_block_height {
333351
// 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 }));
335353
}
336354

337355
let block_status = maybe_await!(self.client.get_block_status(&block_hash))?;
338356
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 }));
340358
} else {
341359
// If any previously-confirmed block suddenly is no longer confirmed, we found
342360
// an inconsistency and should start over.

0 commit comments

Comments
 (0)