@@ -314,32 +314,42 @@ impl FeeEstimator for BitcoindClient {
314
314
315
315
impl BroadcasterInterface for BitcoindClient {
316
316
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] )
329
332
. 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: {}\n Transaction: {}" ,
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: {}\n Transactions: {:?}" ,
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
+ } ) ;
343
353
}
344
354
}
345
355
0 commit comments