Skip to content

Commit 7ca1088

Browse files
committed
Switch to submitpackage for broadcasting transactions
1 parent c52bf5b commit 7ca1088

File tree

1 file changed

+35
-25
lines changed

1 file changed

+35
-25
lines changed

src/bitcoind_client.rs

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -314,32 +314,42 @@ impl FeeEstimator for BitcoindClient {
314314

315315
impl BroadcasterInterface for BitcoindClient {
316316
fn broadcast_transactions(&self, txs: &[&Transaction]) {
317-
// TODO: Rather than calling `sendrawtransaction` in a a loop, we should probably use
318-
// `submitpackage` once it becomes available.
319-
for tx in txs {
320-
let bitcoind_rpc_client = Arc::clone(&self.bitcoind_rpc_client);
321-
let tx_serialized = encode::serialize_hex(tx);
322-
let tx_json = serde_json::json!(tx_serialized);
323-
let logger = Arc::clone(&self.logger);
324-
self.handle.spawn(async move {
325-
// This may error due to RL calling `broadcast_transactions` with the same transaction
326-
// multiple times, but the error is safe to ignore.
327-
match bitcoind_rpc_client
328-
.call_method::<Txid>("sendrawtransaction", &vec![tx_json])
317+
// As of Bitcoin Core 28, using `submitpackage` allows us to broadcast multiple
318+
// transactions at once and have them propagate through the network as a whole, avoiding
319+
// some pitfalls with anchor channels where the first transaction doesn't make it into the
320+
// mempool at all. Several older versions of Bitcoin Core also support `submitpackage`,
321+
// however, so we just use it unconditionally here.
322+
// Sadly, Bitcoin Core has an arbitrary restriction on `submitpackage` - it must actually
323+
// contain a package (see https://github.com/bitcoin/bitcoin/issues/31085).
324+
let txn = txs.iter().map(|tx| encode::serialize_hex(tx)).collect::<Vec<_>>();
325+
let bitcoind_rpc_client = Arc::clone(&self.bitcoind_rpc_client);
326+
let logger = Arc::clone(&self.logger);
327+
self.handle.spawn(async move {
328+
let res = if txn.len() == 1 {
329+
let tx_json = serde_json::json!(txn[0]);
330+
bitcoind_rpc_client
331+
.call_method::<serde_json::Value>("sendrawtransaction", &[tx_json])
329332
.await
330-
{
331-
Ok(_) => {}
332-
Err(e) => {
333-
let err_str = e.get_ref().unwrap().to_string();
334-
log_error!(logger,
335-
"Warning, failed to broadcast a transaction, this is likely okay but may indicate an error: {}\nTransaction: {}",
336-
err_str,
337-
tx_serialized);
338-
print!("Warning, failed to broadcast a transaction, this is likely okay but may indicate an error: {}\n> ", err_str);
339-
}
340-
}
341-
});
342-
}
333+
} else {
334+
let tx_json = serde_json::json!(txn);
335+
bitcoind_rpc_client
336+
.call_method::<serde_json::Value>("submitpackage", &[tx_json])
337+
.await
338+
};
339+
// This may error due to RL calling `broadcast_transactions` with the same transaction
340+
// multiple times, but the error is safe to ignore.
341+
match res {
342+
Ok(_) => {}
343+
Err(e) => {
344+
let err_str = e.get_ref().unwrap().to_string();
345+
log_error!(logger,
346+
"Warning, failed to broadcast a transaction, this is likely okay but may indicate an error: {}\nTransactions: {:?}",
347+
err_str,
348+
txn);
349+
print!("Warning, failed to broadcast a transaction, this is likely okay but may indicate an error: {}\n> ", err_str);
350+
}
351+
}
352+
});
343353
}
344354
}
345355

0 commit comments

Comments
 (0)