Skip to content

Commit 8a9caaf

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 3363c9b commit 8a9caaf

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};
@@ -244,31 +245,54 @@ impl Wallet {
244245
self.pending_payment_store.insert_or_update(pending_payment)?;
245246
},
246247
WalletEvent::ChainTipChanged { new_tip, .. } => {
247-
// Get all payments that are Pending with Confirmed status
248+
// Get all on-chain payments that are Pending
248249
let pending_payments: Vec<PendingPaymentDetails> =
249250
self.pending_payment_store.list_filter(|p| {
250251
p.details.status == PaymentStatus::Pending
251-
&& matches!(
252-
p.details.kind,
253-
PaymentKind::Onchain {
254-
status: ConfirmationStatus::Confirmed { .. },
255-
..
256-
}
257-
)
252+
&& matches!(p.details.kind, PaymentKind::Onchain { .. })
258253
});
259254

255+
let mut unconfirmed_outbound_txids: Vec<Txid> = Vec::new();
256+
260257
for mut payment in pending_payments {
261-
if let PaymentKind::Onchain {
262-
status: ConfirmationStatus::Confirmed { height, .. },
263-
..
264-
} = payment.details.kind
265-
{
266-
let payment_id = payment.details.id;
267-
if new_tip.height >= height + ANTI_REORG_DELAY - 1 {
268-
payment.details.status = PaymentStatus::Succeeded;
269-
self.payment_store.insert_or_update(payment.details)?;
270-
self.pending_payment_store.remove(&payment_id)?;
271-
}
258+
match payment.details.kind {
259+
PaymentKind::Onchain {
260+
status: ConfirmationStatus::Confirmed { height, .. },
261+
..
262+
} => {
263+
let payment_id = payment.details.id;
264+
if new_tip.height >= height + ANTI_REORG_DELAY - 1 {
265+
payment.details.status = PaymentStatus::Succeeded;
266+
self.payment_store.insert_or_update(payment.details)?;
267+
self.pending_payment_store.remove(&payment_id)?;
268+
}
269+
},
270+
PaymentKind::Onchain {
271+
txid,
272+
status: ConfirmationStatus::Unconfirmed,
273+
} if payment.details.direction == PaymentDirection::Outbound => {
274+
unconfirmed_outbound_txids.push(txid);
275+
},
276+
_ => {},
277+
}
278+
}
279+
280+
if !unconfirmed_outbound_txids.is_empty() {
281+
let txs_to_broadcast: Vec<Transaction> = unconfirmed_outbound_txids
282+
.iter()
283+
.filter_map(|txid| {
284+
locked_wallet.tx_details(*txid).map(|d| (*d.tx).clone())
285+
})
286+
.collect();
287+
288+
if !txs_to_broadcast.is_empty() {
289+
let tx_refs: Vec<&Transaction> = txs_to_broadcast.iter().collect();
290+
self.broadcaster.broadcast_transactions(&tx_refs);
291+
log_info!(
292+
self.logger,
293+
"Rebroadcast {} unconfirmed transactions on chain tip change",
294+
txs_to_broadcast.len()
295+
);
272296
}
273297
}
274298
},

0 commit comments

Comments
 (0)