From 9635806fc4c065520d50588befbf30a4577fef53 Mon Sep 17 00:00:00 2001 From: Richard Holzeis Date: Mon, 17 Jun 2024 16:42:28 +0200 Subject: [PATCH] fix: Only accept a rollover offer if the contract has been confirmed. Syncs the wallet eagerly if the channel is not yet confirmed. If the contract is not confirmed, the rollover offer gets rejected. This fixes an issue where the app otherwise risk ending up in an intermediate state as it can't accept the `RenewConfirm` message. see https://github.com/get10101/10101/issues/2630 --- mobile/native/src/dlc/node.rs | 91 +++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/mobile/native/src/dlc/node.rs b/mobile/native/src/dlc/node.rs index 9a4836464..5d32d2c07 100644 --- a/mobile/native/src/dlc/node.rs +++ b/mobile/native/src/dlc/node.rs @@ -1,4 +1,5 @@ use crate::db; +use crate::dlc::check_if_signed_channel_is_confirmed; use crate::event; use crate::event::BackgroundTask; use crate::event::EventInternal; @@ -26,6 +27,7 @@ use dlc_messages::channel::OfferChannel; use dlc_messages::channel::Reject; use dlc_messages::channel::RenewOffer; use dlc_messages::channel::SettleOffer; +use futures::executor::block_on; use itertools::Itertools; use lightning::chain::transaction::OutPoint; use lightning::sign::DelayedPaymentOutputDescriptor; @@ -744,46 +746,61 @@ impl Node { )?; let channel_id = offer.renew_offer.channel_id; + if !block_on(check_if_signed_channel_is_confirmed())? { + tracing::warn!( + "Rejecting rollover offer as the DLC channel has not been confirmed yet." + ); - match self.inner.dlc_manager.accept_renew_offer(&channel_id) { - Ok((renew_accept, node_id)) => { - let positions = get_positions()?; - let position = positions.first().context("No position to roll over")?; - - let new_unpaid_funding_fee_events = handle_unpaid_funding_fee_events( - &offer - .funding_fee_events - .iter() - .map(|e| { - FundingFeeEvent::unpaid( - position.contract_symbol, - Decimal::try_from(position.quantity).expect("to fit"), - position.direction, - e.price, - e.funding_fee, - e.due_date, - ) - }) - .collect_vec(), - )?; - - handle_rollover_offer(expiry_timestamp, &new_unpaid_funding_fee_events)?; - - self.send_dlc_message( - to_secp_pk_30(node_id), - TenTenOneMessage::RolloverAccept(TenTenOneRolloverAccept { renew_accept }), - )?; - } - Err(e) => { - tracing::error!("Failed to accept DLC channel rollover offer: {e}"); + event::publish(&EventInternal::BackgroundNotification( + BackgroundTask::Rollover(TaskStatus::Failed( + "Failed to rollover with unconfirmed DLC channel.".to_string(), + )), + )); + + self.reject_rollover_offer(&channel_id)?; + } else { + tracing::warn!("DLC channel is confirmed. Accepting rollover offer."); + + match self.inner.dlc_manager.accept_renew_offer(&channel_id) { + Ok((renew_accept, node_id)) => { + let positions = get_positions()?; + let position = positions.first().context("No position to roll over")?; + + let new_unpaid_funding_fee_events = handle_unpaid_funding_fee_events( + &offer + .funding_fee_events + .iter() + .map(|e| { + FundingFeeEvent::unpaid( + position.contract_symbol, + Decimal::try_from(position.quantity).expect("to fit"), + position.direction, + e.price, + e.funding_fee, + e.due_date, + ) + }) + .collect_vec(), + )?; + + handle_rollover_offer(expiry_timestamp, &new_unpaid_funding_fee_events)?; + + self.send_dlc_message( + to_secp_pk_30(node_id), + TenTenOneMessage::RolloverAccept(TenTenOneRolloverAccept { renew_accept }), + )?; + } + Err(e) => { + tracing::error!("Failed to accept DLC channel rollover offer: {e}"); - event::publish(&EventInternal::BackgroundNotification( - BackgroundTask::Rollover(TaskStatus::Failed(format!("{e}"))), - )); + event::publish(&EventInternal::BackgroundNotification( + BackgroundTask::Rollover(TaskStatus::Failed(format!("{e}"))), + )); - self.reject_rollover_offer(&channel_id)?; - } - }; + self.reject_rollover_offer(&channel_id)?; + } + }; + } Ok(()) }