diff --git a/src/lib.rs b/src/lib.rs index 4948b192c..807bf617b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -135,8 +135,8 @@ use graph::NetworkGraph; use liquidity::LiquiditySource; use payment::store::PaymentStore; use payment::{ - Bolt11Payment, Bolt12Payment, OnchainPayment, PayjoinPayment, PaymentDetails, SpontaneousPayment, - UnifiedQrPayment, + Bolt11Payment, Bolt12Payment, OnchainPayment, PayjoinPayment, PaymentDetails, + SpontaneousPayment, UnifiedQrPayment, }; use peer_store::{PeerInfo, PeerStore}; use types::{ @@ -382,6 +382,10 @@ impl Node { let archive_cmon = Arc::clone(&self.chain_monitor); let sync_sweeper = Arc::clone(&self.output_sweeper); let sync_logger = Arc::clone(&self.logger); + let sync_payjoin = match &self.payjoin_handler { + Some(pj_handler) => Some(Arc::clone(pj_handler)), + None => None, + }; let sync_wallet_timestamp = Arc::clone(&self.latest_wallet_sync_timestamp); let sync_monitor_archival_height = Arc::clone(&self.latest_channel_monitor_archival_height); let mut stop_sync = self.stop_sender.subscribe(); @@ -401,11 +405,14 @@ impl Node { return; } _ = wallet_sync_interval.tick() => { - let confirmables = vec![ + let mut confirmables = vec![ &*sync_cman as &(dyn Confirm + Sync + Send), &*sync_cmon as &(dyn Confirm + Sync + Send), &*sync_sweeper as &(dyn Confirm + Sync + Send), ]; + if let Some(sync_payjoin) = sync_payjoin.as_ref() { + confirmables.push(sync_payjoin.as_ref() as &(dyn Confirm + Sync + Send)); + } let now = Instant::now(); let timeout_fut = tokio::time::timeout(Duration::from_secs(LDK_WALLET_SYNC_TIMEOUT_SECS), tx_sync.sync(confirmables)); match timeout_fut.await { @@ -1108,7 +1115,8 @@ impl Node { self.bolt12_payment(), Arc::clone(&self.config), Arc::clone(&self.logger), - ))} + )) + } /// Returns a Payjoin payment handler allowing to send Payjoin transactions /// @@ -1347,11 +1355,15 @@ impl Node { let fee_estimator = Arc::clone(&self.fee_estimator); let sync_sweeper = Arc::clone(&self.output_sweeper); let sync_logger = Arc::clone(&self.logger); - let confirmables = vec![ + let sync_payjoin = &self.payjoin_handler.as_ref(); + let mut confirmables = vec![ &*sync_cman as &(dyn Confirm + Sync + Send), &*sync_cmon as &(dyn Confirm + Sync + Send), &*sync_sweeper as &(dyn Confirm + Sync + Send), ]; + if let Some(sync_payjoin) = sync_payjoin { + confirmables.push(sync_payjoin.as_ref() as &(dyn Confirm + Sync + Send)); + } let sync_wallet_timestamp = Arc::clone(&self.latest_wallet_sync_timestamp); let sync_fee_rate_update_timestamp = Arc::clone(&self.latest_fee_rate_cache_update_timestamp); diff --git a/src/payment/payjoin/handler.rs b/src/payment/payjoin/handler.rs index 9073ed3c8..1ec606a2f 100644 --- a/src/payment/payjoin/handler.rs +++ b/src/payment/payjoin/handler.rs @@ -134,80 +134,72 @@ impl PayjoinHandler { ) -> Result { let wallet = self.wallet.clone(); wallet.sign_payjoin_proposal(payjoin_proposal, original_psbt)?; + let proposal_tx = payjoin_proposal.clone().extract_tx(); - match self - .transactions - .read() - .unwrap() - .iter() - .position(|t| t.original_psbt() == original_psbt) - { - Some(pos) => { - let pj_tx = self.transactions.write().unwrap().remove(pos); - pj_tx.waiting_first_confirmation(proposal_tx.clone())?; - let txid = proposal_tx.txid(); - // watch proposal transaction - self.chain_source.register_tx(&txid, Script::empty()); - Ok(proposal_tx) - }, - None => { - log_error!( - self.logger, - "Failed to process Payjoin response: transaction not found" - ); - Err(Error::PayjoinResponseProcessingFailed) - }, + let mut transactions = self.transactions.write().unwrap(); + let pos = transactions.iter().position(|t| t.original_psbt() == original_psbt); + if let Some(pos) = pos { + let pj_tx = transactions.remove(pos); + pj_tx.waiting_first_confirmation(proposal_tx.clone())?; + let txid = proposal_tx.txid(); + // watch proposal transaction + self.chain_source.register_tx(&txid, Script::empty()); + self.event_queue.add_event(Event::PayjoinPaymentBroadcasted { + txid, + amount_sats: pj_tx.amount().to_sat(), + recipient: pj_tx.receiver().clone().into(), + })?; + Ok(proposal_tx) + } else { + log_error!(self.logger, "Failed to process Payjoin response: transaction not found"); + Err(Error::PayjoinResponseProcessingFailed) } } pub(crate) fn handle_request_failure( &self, original_psbt: &Psbt, reason: PayjoinPaymentFailureReason, ) -> Result<(), Error> { - match self - .transactions - .read() - .unwrap() - .iter() - .position(|o| o.original_psbt() == original_psbt) - { - Some(pos) => { - let mut transactions = self.transactions.write().unwrap(); - let tx = transactions.remove(pos); - let payment_id: [u8; 32] = - tx.original_psbt().unsigned_tx.txid()[..].try_into().map_err(|_| { - log_error!( + let mut transactions = self.transactions.write().unwrap(); + let pos = transactions.iter().position(|t| t.original_psbt() == original_psbt); + if let Some(pos) = pos { + let tx = transactions.remove(pos); + let payment_id: [u8; 32] = + tx.original_psbt().unsigned_tx.txid()[..].try_into().map_err(|_| { + log_error!( self.logger, "Failed to handle request failure for Payjoin payment: invalid payment id" ); - Error::PayjoinRequestSendingFailed - })?; - let mut update_details = PaymentDetailsUpdate::new(PaymentId(payment_id)); - update_details.status = Some(PaymentStatus::Failed); - let _ = self.payment_store.update(&update_details); - self.event_queue.add_event(Event::PayjoinPaymentFailed { - txid: original_psbt.unsigned_tx.txid(), - recipient: tx.receiver().clone().into(), - amount_sats: tx.amount().to_sat(), - reason, - }) - }, - None => { - log_error!( - self.logger, - "Failed to handle request failure for Payjoin payment: transaction not found" - ); - Err(Error::PayjoinRequestSendingFailed) - }, + Error::PayjoinRequestSendingFailed + })?; + let mut update_details = PaymentDetailsUpdate::new(PaymentId(payment_id)); + update_details.status = Some(PaymentStatus::Failed); + let _ = self.payment_store.update(&update_details); + self.event_queue.add_event(Event::PayjoinPaymentFailed { + txid: original_psbt.unsigned_tx.txid(), + recipient: tx.receiver().clone().into(), + amount_sats: tx.amount().to_sat(), + reason, + }) + } + else { + log_error!( + self.logger, + "Failed to handle request failure for Payjoin payment: transaction not found" + ); + Err(Error::PayjoinRequestSendingFailed) } } fn internal_transactions_confirmed( &self, header: &Header, txdata: &TransactionData, height: u32, ) { + dbg!("internal transactions confirmed"); let (_, tx) = txdata[0]; let confirmed_tx_txid = tx.txid(); let mut transactions = self.transactions.write().unwrap(); - if let Some(pos) = transactions.iter().position(|o| o.txid() == confirmed_tx_txid) { + let pos = transactions.iter().position(|t| t.txid() == confirmed_tx_txid); + dbg!(&pos); + if let Some(pos) = pos { match transactions.remove(pos) { PayjoinTransaction::PendingReceiverResponse { original_psbt, receiver, amount } => { println!("Payjoin receiver broadcasted original psbt transaction!"); @@ -300,6 +292,7 @@ impl PayjoinHandler { } } + impl Confirm for PayjoinHandler { fn transactions_confirmed(&self, header: &Header, txdata: &TransactionData, height: u32) { self.internal_transactions_confirmed(header, txdata, height); diff --git a/src/payment/payjoin/mod.rs b/src/payment/payjoin/mod.rs index 07c93470b..2029f4a23 100644 --- a/src/payment/payjoin/mod.rs +++ b/src/payment/payjoin/mod.rs @@ -132,10 +132,12 @@ impl PayjoinPayment { break; }, Ok(None) => { + dbg!("Payjoin request sent, waiting for response..."); log_info!(logger, "Payjoin request sent, waiting for response..."); continue; } Err(e) => { + dbg!(&e); log_error!(logger, "Failed to send Payjoin request : {}", e); let _ = payjoin_handler.handle_request_failure(&original_psbt, PayjoinPaymentFailureReason::RequestSendingFailed); break;