Skip to content

Commit 6775b95

Browse files
authored
Merge pull request #2272 from benthecarman/package-broadcast
Support broadcasting multiple transactions at once
2 parents bada713 + 29b392a commit 6775b95

File tree

7 files changed

+41
-22
lines changed

7 files changed

+41
-22
lines changed

fuzz/src/chanmon_consistency.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl Router for FuzzRouter {
100100

101101
pub struct TestBroadcaster {}
102102
impl BroadcasterInterface for TestBroadcaster {
103-
fn broadcast_transaction(&self, _tx: &Transaction) { }
103+
fn broadcast_transactions(&self, _txs: &[&Transaction]) { }
104104
}
105105

106106
pub struct VecWriter(pub Vec<u8>);

fuzz/src/full_stack.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ struct TestBroadcaster {
144144
txn_broadcasted: Mutex<Vec<Transaction>>,
145145
}
146146
impl BroadcasterInterface for TestBroadcaster {
147-
fn broadcast_transaction(&self, tx: &Transaction) {
148-
self.txn_broadcasted.lock().unwrap().push(tx.clone());
147+
fn broadcast_transactions(&self, txs: &[&Transaction]) {
148+
let owned_txs: Vec<Transaction> = txs.iter().map(|tx| (*tx).clone()).collect();
149+
self.txn_broadcasted.lock().unwrap().extend(owned_txs);
149150
}
150151
}
151152

lightning/src/chain/chaininterface.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,20 @@ use bitcoin::blockdata::transaction::Transaction;
1919

2020
/// An interface to send a transaction to the Bitcoin network.
2121
pub trait BroadcasterInterface {
22-
/// Sends a transaction out to (hopefully) be mined.
23-
fn broadcast_transaction(&self, tx: &Transaction);
22+
/// Sends a list of transactions out to (hopefully) be mined.
23+
/// This only needs to handle the actual broadcasting of transactions, LDK will automatically
24+
/// rebroadcast transactions that haven't made it into a block.
25+
///
26+
/// In some cases LDK may attempt to broadcast a transaction which double-spends another
27+
/// and this isn't a bug and can be safely ignored.
28+
///
29+
/// If more than one transaction is given, these transactions should be considered to be a
30+
/// package and broadcast together. Some of the transactions may or may not depend on each other,
31+
/// be sure to manage both cases correctly.
32+
///
33+
/// Bitcoin transaction packages are defined in BIP 331 and here:
34+
/// https://github.com/bitcoin/bitcoin/blob/master/doc/policy/packages.md
35+
fn broadcast_transactions(&self, txs: &[&Transaction]);
2436
}
2537

2638
/// An enum that represents the speed at which we want a transaction to confirm used for feerate

lightning/src/chain/channelmonitor.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -2327,10 +2327,13 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
23272327
where B::Target: BroadcasterInterface,
23282328
L::Target: Logger,
23292329
{
2330-
for tx in self.get_latest_holder_commitment_txn(logger).iter() {
2330+
let commit_txs = self.get_latest_holder_commitment_txn(logger);
2331+
let mut txs = vec![];
2332+
for tx in commit_txs.iter() {
23312333
log_info!(logger, "Broadcasting local {}", log_tx!(tx));
2332-
broadcaster.broadcast_transaction(tx);
2334+
txs.push(tx);
23332335
}
2336+
broadcaster.broadcast_transactions(&txs);
23342337
self.pending_monitor_events.push(MonitorEvent::CommitmentTxConfirmed(self.funding_info.0));
23352338
}
23362339

lightning/src/chain/onchaintx.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
513513
OnchainClaim::Tx(tx) => {
514514
let log_start = if bumped_feerate { "Broadcasting RBF-bumped" } else { "Rebroadcasting" };
515515
log_info!(logger, "{} onchain {}", log_start, log_tx!(tx));
516-
broadcaster.broadcast_transaction(&tx);
516+
broadcaster.broadcast_transactions(&[&tx]);
517517
},
518518
#[cfg(anchors)]
519519
OnchainClaim::Event(event) => {
@@ -767,7 +767,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
767767
let package_id = match claim {
768768
OnchainClaim::Tx(tx) => {
769769
log_info!(logger, "Broadcasting onchain {}", log_tx!(tx));
770-
broadcaster.broadcast_transaction(&tx);
770+
broadcaster.broadcast_transactions(&[&tx]);
771771
tx.txid().into_inner()
772772
},
773773
#[cfg(anchors)]
@@ -960,7 +960,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
960960
match bump_claim {
961961
OnchainClaim::Tx(bump_tx) => {
962962
log_info!(logger, "Broadcasting RBF-bumped onchain {}", log_tx!(bump_tx));
963-
broadcaster.broadcast_transaction(&bump_tx);
963+
broadcaster.broadcast_transactions(&[&bump_tx]);
964964
},
965965
#[cfg(anchors)]
966966
OnchainClaim::Event(claim_event) => {
@@ -1046,7 +1046,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
10461046
match bump_claim {
10471047
OnchainClaim::Tx(bump_tx) => {
10481048
log_info!(logger, "Broadcasting onchain {}", log_tx!(bump_tx));
1049-
broadcaster.broadcast_transaction(&bump_tx);
1049+
broadcaster.broadcast_transactions(&[&bump_tx]);
10501050
},
10511051
#[cfg(anchors)]
10521052
OnchainClaim::Event(claim_event) => {

lightning/src/ln/channelmanager.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -4517,7 +4517,7 @@ where
45174517

45184518
if let Some(tx) = funding_broadcastable {
45194519
log_info!(self.logger, "Broadcasting funding transaction with txid {}", tx.txid());
4520-
self.tx_broadcaster.broadcast_transaction(&tx);
4520+
self.tx_broadcaster.broadcast_transactions(&[&tx]);
45214521
}
45224522

45234523
{
@@ -5047,7 +5047,7 @@ where
50475047
};
50485048
if let Some(broadcast_tx) = tx {
50495049
log_info!(self.logger, "Broadcasting {}", log_tx!(broadcast_tx));
5050-
self.tx_broadcaster.broadcast_transaction(&broadcast_tx);
5050+
self.tx_broadcaster.broadcast_transactions(&[&broadcast_tx]);
50515051
}
50525052
if let Some(chan) = chan_option {
50535053
if let Ok(update) = self.get_channel_update_for_broadcast(&chan) {
@@ -5657,7 +5657,7 @@ where
56575657
self.issue_channel_close_events(chan, ClosureReason::CooperativeClosure);
56585658

56595659
log_info!(self.logger, "Broadcasting {}", log_tx!(tx));
5660-
self.tx_broadcaster.broadcast_transaction(&tx);
5660+
self.tx_broadcaster.broadcast_transactions(&[&tx]);
56615661
update_maps_on_chan_removal!(self, chan);
56625662
false
56635663
} else { true }

lightning/src/util/test_utils.rs

+11-8
Original file line numberDiff line numberDiff line change
@@ -341,17 +341,20 @@ impl TestBroadcaster {
341341
}
342342

343343
impl chaininterface::BroadcasterInterface for TestBroadcaster {
344-
fn broadcast_transaction(&self, tx: &Transaction) {
345-
let lock_time = tx.lock_time.0;
346-
assert!(lock_time < 1_500_000_000);
347-
if bitcoin::LockTime::from(tx.lock_time).is_block_height() && lock_time > self.blocks.lock().unwrap().last().unwrap().1 {
348-
for inp in tx.input.iter() {
349-
if inp.sequence != Sequence::MAX {
350-
panic!("We should never broadcast a transaction before its locktime ({})!", tx.lock_time);
344+
fn broadcast_transactions(&self, txs: &[&Transaction]) {
345+
for tx in txs {
346+
let lock_time = tx.lock_time.0;
347+
assert!(lock_time < 1_500_000_000);
348+
if bitcoin::LockTime::from(tx.lock_time).is_block_height() && lock_time > self.blocks.lock().unwrap().last().unwrap().1 {
349+
for inp in tx.input.iter() {
350+
if inp.sequence != Sequence::MAX {
351+
panic!("We should never broadcast a transaction before its locktime ({})!", tx.lock_time);
352+
}
351353
}
352354
}
353355
}
354-
self.txn_broadcasted.lock().unwrap().push(tx.clone());
356+
let owned_txs: Vec<Transaction> = txs.iter().map(|tx| (*tx).clone()).collect();
357+
self.txn_broadcasted.lock().unwrap().extend(owned_txs);
355358
}
356359
}
357360

0 commit comments

Comments
 (0)