@@ -5,15 +5,15 @@ use crate::convert::{
55use crate :: disk:: FilesystemLogger ;
66use crate :: hex_utils;
77use base64;
8- use bitcoin:: address:: { Address , Payload , WitnessVersion } ;
8+ use bitcoin:: address:: Address ;
99use bitcoin:: blockdata:: constants:: WITNESS_SCALE_FACTOR ;
1010use bitcoin:: blockdata:: script:: ScriptBuf ;
1111use bitcoin:: blockdata:: transaction:: Transaction ;
1212use bitcoin:: consensus:: { encode, Decodable , Encodable } ;
1313use bitcoin:: hash_types:: { BlockHash , Txid } ;
1414use bitcoin:: hashes:: Hash ;
1515use bitcoin:: key:: XOnlyPublicKey ;
16- use bitcoin:: psbt:: PartiallySignedTransaction ;
16+ use bitcoin:: psbt:: Psbt ;
1717use bitcoin:: { Network , OutPoint , TxOut , WPubkeyHash } ;
1818use lightning:: chain:: chaininterface:: { BroadcasterInterface , ConfirmationTarget , FeeEstimator } ;
1919use lightning:: events:: bump_transaction:: { Utxo , WalletSource } ;
@@ -80,7 +80,8 @@ impl BitcoindClient {
8080 "Failed to make initial call to bitcoind - please check your RPC user/password and access settings" )
8181 } ) ?;
8282 let mut fees: HashMap < ConfirmationTarget , AtomicU32 > = HashMap :: new ( ) ;
83- fees. insert ( ConfirmationTarget :: OnChainSweep , AtomicU32 :: new ( 5000 ) ) ;
83+ fees. insert ( ConfirmationTarget :: MaximumFeeEstimate , AtomicU32 :: new ( 50000 ) ) ;
84+ fees. insert ( ConfirmationTarget :: UrgentOnChainSweep , AtomicU32 :: new ( 5000 ) ) ;
8485 fees. insert (
8586 ConfirmationTarget :: MinAllowedAnchorChannelRemoteFee ,
8687 AtomicU32 :: new ( MIN_FEERATE ) ,
@@ -92,6 +93,7 @@ impl BitcoindClient {
9293 fees. insert ( ConfirmationTarget :: AnchorChannelFee , AtomicU32 :: new ( MIN_FEERATE ) ) ;
9394 fees. insert ( ConfirmationTarget :: NonAnchorChannelFee , AtomicU32 :: new ( 2000 ) ) ;
9495 fees. insert ( ConfirmationTarget :: ChannelCloseMinimum , AtomicU32 :: new ( MIN_FEERATE ) ) ;
96+ fees. insert ( ConfirmationTarget :: OutputSpendingFee , AtomicU32 :: new ( MIN_FEERATE ) ) ;
9597
9698 let client = Self {
9799 bitcoind_rpc_client : Arc :: new ( bitcoind_rpc_client) ,
@@ -177,7 +179,27 @@ impl BitcoindClient {
177179 }
178180 } ;
179181
180- fees. get ( & ConfirmationTarget :: OnChainSweep )
182+ let very_high_prio_estimate = {
183+ let high_prio_conf_target = serde_json:: json!( 2 ) ;
184+ let high_prio_estimate_mode = serde_json:: json!( "CONSERVATIVE" ) ;
185+ let resp = rpc_client
186+ . call_method :: < FeeResponse > (
187+ "estimatesmartfee" ,
188+ & vec ! [ high_prio_conf_target, high_prio_estimate_mode] ,
189+ )
190+ . await
191+ . unwrap ( ) ;
192+
193+ match resp. feerate_sat_per_kw {
194+ Some ( feerate) => std:: cmp:: max ( feerate, MIN_FEERATE ) ,
195+ None => 50000 ,
196+ }
197+ } ;
198+
199+ fees. get ( & ConfirmationTarget :: MaximumFeeEstimate )
200+ . unwrap ( )
201+ . store ( very_high_prio_estimate, Ordering :: Release ) ;
202+ fees. get ( & ConfirmationTarget :: UrgentOnChainSweep )
181203 . unwrap ( )
182204 . store ( high_prio_estimate, Ordering :: Release ) ;
183205 fees. get ( & ConfirmationTarget :: MinAllowedAnchorChannelRemoteFee )
@@ -195,6 +217,9 @@ impl BitcoindClient {
195217 fees. get ( & ConfirmationTarget :: ChannelCloseMinimum )
196218 . unwrap ( )
197219 . store ( background_estimate, Ordering :: Release ) ;
220+ fees. get ( & ConfirmationTarget :: OutputSpendingFee )
221+ . unwrap ( )
222+ . store ( background_estimate, Ordering :: Release ) ;
198223
199224 tokio:: time:: sleep ( Duration :: from_secs ( 60 ) ) . await ;
200225 }
@@ -289,32 +314,42 @@ impl FeeEstimator for BitcoindClient {
289314
290315impl BroadcasterInterface for BitcoindClient {
291316 fn broadcast_transactions ( & self , txs : & [ & Transaction ] ) {
292- // TODO: Rather than calling `sendrawtransaction` in a a loop, we should probably use
293- // `submitpackage` once it becomes available.
294- for tx in txs {
295- let bitcoind_rpc_client = Arc :: clone ( & self . bitcoind_rpc_client ) ;
296- let tx_serialized = encode:: serialize_hex ( tx) ;
297- let tx_json = serde_json:: json!( tx_serialized) ;
298- let logger = Arc :: clone ( & self . logger ) ;
299- self . handle . spawn ( async move {
300- // This may error due to RL calling `broadcast_transactions` with the same transaction
301- // multiple times, but the error is safe to ignore.
302- match bitcoind_rpc_client
303- . 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] )
304332 . await
305- {
306- Ok ( _) => { }
307- Err ( e) => {
308- let err_str = e. get_ref ( ) . unwrap ( ) . to_string ( ) ;
309- log_error ! ( logger,
310- "Warning, failed to broadcast a transaction, this is likely okay but may indicate an error: {}\n Transaction: {}" ,
311- err_str,
312- tx_serialized) ;
313- print ! ( "Warning, failed to broadcast a transaction, this is likely okay but may indicate an error: {}\n > " , err_str) ;
314- }
315- }
316- } ) ;
317- }
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+ } ) ;
318353 }
319354}
320355
@@ -335,24 +370,26 @@ impl WalletSource for BitcoindClient {
335370 . into_iter ( )
336371 . filter_map ( |utxo| {
337372 let outpoint = OutPoint { txid : utxo. txid , vout : utxo. vout } ;
338- match utxo. address . payload . clone ( ) {
339- Payload :: WitnessProgram ( wp) => match wp. version ( ) {
340- WitnessVersion :: V0 => WPubkeyHash :: from_slice ( wp. program ( ) . as_bytes ( ) )
341- . map ( |wpkh| Utxo :: new_v0_p2wpkh ( outpoint, utxo. amount , & wpkh) )
342- . ok ( ) ,
373+ let value = bitcoin:: Amount :: from_sat ( utxo. amount ) ;
374+ match utxo. address . witness_program ( ) {
375+ Some ( prog) if prog. is_p2wpkh ( ) => {
376+ WPubkeyHash :: from_slice ( prog. program ( ) . as_bytes ( ) )
377+ . map ( |wpkh| Utxo :: new_v0_p2wpkh ( outpoint, value, & wpkh) )
378+ . ok ( )
379+ } ,
380+ Some ( prog) if prog. is_p2tr ( ) => {
343381 // TODO: Add `Utxo::new_v1_p2tr` upstream.
344- WitnessVersion :: V1 => XOnlyPublicKey :: from_slice ( wp . program ( ) . as_bytes ( ) )
382+ XOnlyPublicKey :: from_slice ( prog . program ( ) . as_bytes ( ) )
345383 . map ( |_| Utxo {
346384 outpoint,
347385 output : TxOut {
348- value : utxo . amount ,
349- script_pubkey : ScriptBuf :: new_witness_program ( & wp ) ,
386+ value,
387+ script_pubkey : utxo . address . script_pubkey ( ) ,
350388 } ,
351389 satisfaction_weight : 1 /* empty script_sig */ * WITNESS_SCALE_FACTOR as u64 +
352390 1 /* witness items */ + 1 /* schnorr sig len */ + 64 , /* schnorr sig */
353391 } )
354- . ok ( ) ,
355- _ => None ,
392+ . ok ( )
356393 } ,
357394 _ => None ,
358395 }
@@ -366,7 +403,7 @@ impl WalletSource for BitcoindClient {
366403 } )
367404 }
368405
369- fn sign_psbt ( & self , tx : PartiallySignedTransaction ) -> Result < Transaction , ( ) > {
406+ fn sign_psbt ( & self , tx : Psbt ) -> Result < Transaction , ( ) > {
370407 let mut tx_bytes = Vec :: new ( ) ;
371408 let _ = tx. unsigned_tx . consensus_encode ( & mut tx_bytes) . map_err ( |_| ( ) ) ;
372409 let tx_hex = hex_utils:: hex_str ( & tx_bytes) ;
0 commit comments