@@ -3,9 +3,16 @@ pub mod poller;
33pub mod utils;
44
55use crate :: config:: BitcoindConfig ;
6- use crate :: { database:: DatabaseError , revaultd:: RevaultD , threadmessages:: BitcoindMessageOut } ;
6+ use crate :: {
7+ database:: {
8+ interface:: { db_spend_transaction, db_vault_by_unvault_txid} ,
9+ DatabaseError ,
10+ } ,
11+ revaultd:: RevaultD ,
12+ threadmessages:: BitcoindMessageOut ,
13+ } ;
714use interface:: { BitcoinD , WalletTransaction } ;
8- use poller:: poller_main;
15+ use poller:: { cpfp_package , poller_main, should_manual_cpfp , ToBeCpfped } ;
916use revault_tx:: bitcoin:: { Network , Txid } ;
1017
1118use std:: {
@@ -187,6 +194,55 @@ fn wallet_transaction(bitcoind: &BitcoinD, txid: Txid) -> Option<WalletTransacti
187194 . ok ( )
188195}
189196
197+ fn cpfp (
198+ revaultd : Arc < RwLock < RevaultD > > ,
199+ bitcoind : Arc < RwLock < BitcoinD > > ,
200+ txids : Vec < Txid > ,
201+ feerate : f64 ,
202+ ) -> Result < ( ) , BitcoindError > {
203+ let db_path = revaultd. read ( ) . unwrap ( ) . db_file ( ) ;
204+ assert ! ( revaultd. read( ) . unwrap( ) . is_manager( ) ) ;
205+
206+ let mut cpfp_txs = Vec :: with_capacity ( txids. len ( ) ) ;
207+ let mut counter = 0 ;
208+
209+ for txid in txids. iter ( ) {
210+ let spend_tx = db_spend_transaction ( & db_path, & txid) . expect ( "Database must be available" ) ;
211+
212+ if let Some ( unwrap_spend_tx) = spend_tx {
213+ // If the transaction is of type SpendTransaction
214+ if should_manual_cpfp ( & bitcoind. read ( ) . unwrap ( ) , * txid) {
215+ cpfp_txs. push ( ToBeCpfped :: Spend ( unwrap_spend_tx. psbt ) ) ;
216+ counter += 1 ;
217+ }
218+ } else {
219+ let unvault_pair =
220+ db_vault_by_unvault_txid ( & db_path, & txid) . expect ( "Database must be available" ) ;
221+ let unvault_tx = match unvault_pair {
222+ Some ( ( _vault, tx) ) => tx,
223+ None => return Err ( BitcoindError :: Custom ( "Unknown Txid." . to_string ( ) ) ) ,
224+ } ;
225+ // The transaction type is asserted to be UnvaultTransaction
226+ if should_manual_cpfp ( & bitcoind. read ( ) . unwrap ( ) , * txid) {
227+ cpfp_txs. push ( ToBeCpfped :: Unvault ( unvault_tx. psbt . assert_unvault ( ) ) ) ;
228+ counter += 1 ;
229+ }
230+ }
231+ }
232+
233+ // sats/vbyte -> sats/WU
234+ let sats_wu = feerate / 4.0 ;
235+ // sats/WU -> msats/WU
236+ let msats_wu = ( sats_wu * 1000.0 ) as u64 ;
237+
238+ if counter != 0 {
239+ cpfp_package ( & revaultd, & bitcoind. read ( ) . unwrap ( ) , cpfp_txs, msats_wu)
240+ } else {
241+ log:: info!( "Nothing to CPFP in the given list." ) ;
242+ Ok ( ( ) )
243+ }
244+ }
245+
190246/// The bitcoind event loop.
191247/// Listens for bitcoind requests (wallet / chain) and poll bitcoind every 30 seconds,
192248/// updating our state accordingly.
@@ -208,7 +264,8 @@ pub fn bitcoind_main_loop(
208264 let _bitcoind = bitcoind. clone ( ) ;
209265 let _sync_progress = sync_progress. clone ( ) ;
210266 let _shutdown = shutdown. clone ( ) ;
211- move || poller_main ( revaultd, _bitcoind, _sync_progress, _shutdown)
267+ let _revaultd = revaultd. clone ( ) ;
268+ move || poller_main ( _revaultd, _bitcoind, _sync_progress, _shutdown)
212269 } ) ;
213270
214271 for msg in rx {
@@ -252,6 +309,16 @@ pub fn bitcoind_main_loop(
252309 ) )
253310 } ) ?;
254311 }
312+ BitcoindMessageOut :: CPFPTransaction ( txids, feerate, resp_tx) => {
313+ log:: trace!( "Received 'cpfptransaction' from main thread" ) ;
314+
315+ resp_tx
316+ . send ( cpfp ( revaultd, bitcoind, txids, feerate) )
317+ . map_err ( |e| {
318+ BitcoindError :: Custom ( format ! ( "Sending transaction for CPFP: {}" , e) )
319+ } ) ?;
320+ return Ok ( ( ) ) ;
321+ }
255322 }
256323 }
257324
0 commit comments