Skip to content

Commit 38f9a87

Browse files
committed
Rebroadcast unconfirmed transactions on each new block
Add automatic rebroadcasting of unconfirmed transactions triggered by the `ChainTipChanged` event from BDK. This ensures pending transactions remain in mempools.
1 parent b55de44 commit 38f9a87

File tree

1 file changed

+43
-19
lines changed

1 file changed

+43
-19
lines changed

src/wallet/mod.rs

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use bitcoin::{
2929
Address, Amount, FeeRate, OutPoint, ScriptBuf, Transaction, TxOut, Txid, WPubkeyHash, Weight,
3030
WitnessProgram, WitnessVersion,
3131
};
32+
3233
use lightning::chain::chaininterface::BroadcasterInterface;
3334
use lightning::chain::channelmonitor::ANTI_REORG_DELAY;
3435
use lightning::chain::{BestBlock, Listen};
@@ -265,31 +266,54 @@ impl Wallet {
265266
self.pending_payment_store.insert_or_update(pending_payment)?;
266267
},
267268
WalletEvent::ChainTipChanged { new_tip, .. } => {
268-
// Get all payments that are Pending with Confirmed status
269+
// Get all on-chain payments that are Pending
269270
let pending_payments: Vec<PendingPaymentDetails> =
270271
self.pending_payment_store.list_filter(|p| {
271272
p.details.status == PaymentStatus::Pending
272-
&& matches!(
273-
p.details.kind,
274-
PaymentKind::Onchain {
275-
status: ConfirmationStatus::Confirmed { .. },
276-
..
277-
}
278-
)
273+
&& matches!(p.details.kind, PaymentKind::Onchain { .. })
279274
});
280275

276+
let mut unconfirmed_outbound_txids: Vec<Txid> = Vec::new();
277+
281278
for mut payment in pending_payments {
282-
if let PaymentKind::Onchain {
283-
status: ConfirmationStatus::Confirmed { height, .. },
284-
..
285-
} = payment.details.kind
286-
{
287-
let payment_id = payment.details.id;
288-
if new_tip.height >= height + ANTI_REORG_DELAY - 1 {
289-
payment.details.status = PaymentStatus::Succeeded;
290-
self.payment_store.insert_or_update(payment.details)?;
291-
self.pending_payment_store.remove(&payment_id)?;
292-
}
279+
match payment.details.kind {
280+
PaymentKind::Onchain {
281+
status: ConfirmationStatus::Confirmed { height, .. },
282+
..
283+
} => {
284+
let payment_id = payment.details.id;
285+
if new_tip.height >= height + ANTI_REORG_DELAY - 1 {
286+
payment.details.status = PaymentStatus::Succeeded;
287+
self.payment_store.insert_or_update(payment.details)?;
288+
self.pending_payment_store.remove(&payment_id)?;
289+
}
290+
},
291+
PaymentKind::Onchain {
292+
txid,
293+
status: ConfirmationStatus::Unconfirmed,
294+
} if payment.details.direction == PaymentDirection::Outbound => {
295+
unconfirmed_outbound_txids.push(txid);
296+
},
297+
_ => {},
298+
}
299+
}
300+
301+
if !unconfirmed_outbound_txids.is_empty() {
302+
let txs_to_broadcast: Vec<Transaction> = unconfirmed_outbound_txids
303+
.iter()
304+
.filter_map(|txid| {
305+
locked_wallet.tx_details(*txid).map(|d| (*d.tx).clone())
306+
})
307+
.collect();
308+
309+
if !txs_to_broadcast.is_empty() {
310+
let tx_refs: Vec<&Transaction> = txs_to_broadcast.iter().collect();
311+
self.broadcaster.broadcast_transactions(&tx_refs);
312+
log_info!(
313+
self.logger,
314+
"Rebroadcast {} unconfirmed transactions on chain tip change",
315+
txs_to_broadcast.len()
316+
);
293317
}
294318
}
295319
},

0 commit comments

Comments
 (0)